3

I have that bash script that shall read the output of git show into an array.

First, I create a string with the following statement:

git show --quiet --date=rfc --pretty=format:"%s|%b|%an, %ae|%H|%cd" HEAD

Which gives me the pattern that I want:

SUBJECT|BODY|AUTHOR_NAME, AUTHOR_EMAIL|COMMIT_HASH|COMMIT_DATE

I can confirm that the resulting string does not contain a | character on an unexpected place.

Next, I want to split up the string into it's fields as supposed in Split string into an array in Bash:

  IFS='|' read -ra FIELDS <<< "$(git show --quiet --date=rfc --pretty=format:"%s|%b|%an, %ae|%H|%cd" $i)"

When I now look at FIELDS, only the first two elements are filled, but the others are empty:

echo ${FIELDS[0]} # prints SUBJECT
echo ${FIELDS[1]} # prints BODY
echo ${FIELDS[2]} # prints nothing
echo ${FIELDS[3]} # prints nothing
echo ${FIELDS[4]} # prints nothing

What am I doing wrong? Why are the last three array elements empty?

Community
  • 1
  • 1
eckes
  • 64,417
  • 29
  • 168
  • 201
  • Can you show the output of the command? In my case, BODY entry is empty, but multiline body comes last. – choroba May 13 '14 at 08:13
  • @choroba: see answer of l0b0 below. The problem is that `git show` terminates the body with a newline which breaks the array creation. – eckes May 13 '14 at 08:25

2 Answers2

4

As @l0b0 pointed out, the problem is caused by a newline in git show's output, right after "BODY" -- the read command reads a single line, so it stops there. You can make it read the whole thing by changing its line delimiter character from newline to... nothing, with read -d '':

IFS='|' read -d '' -ra FIELDS <<< "$(git show --quiet --date=rfc --pretty=format:"%s|%b|%an, %ae|%H|%cd" $i)"

This sets ${FIELDS[0]} to "SUBJECT", ${FIELDS[1]} to "BODY\n", ${FIELDS[2]} to "AUTHOR_NAME, AUTHOR_EMAIL", etc. One complication, however, is that it'll also treat the syntactic newline at the end of the output as part of the last field, i.e. ${FIELDS[4]} will be set to "COMMIT_DATE\n".

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • 1
    Keep in mind that `read -d ''` always exits with status 1, since technically it runs out of input before the line delimiter was found. – chepner May 14 '14 at 14:28
3

The git show command you've given splits the output into multiple lines (at least in version 1.8.3.1), even when passed to another command:

$ git show --quiet --date=rfc --pretty=format:"%s|%b|%an, %ae|%H|%cd" HEAD
SUBJECT|BODY
|AUTHOR_NAME, AUTHOR_EMAIL|COMMIT_HASH|COMMIT_DATE

To work around this you can pipe the output to tr -d '\n' before reading it.

l0b0
  • 55,365
  • 30
  • 138
  • 223
  • Yep. Could confirm this behavior. – eckes May 13 '14 at 08:18
  • using `tr` is not suitable for me since I want to keep the line feeds in the `BODY`. Instead, I'll fetch the body in a second `git show` call and append it to the array manually. Thx! – eckes May 13 '14 at 08:24
  • 1
    You could also use `read -d '' ...` to make it read the entire string in one go (instead of just the first line). – Gordon Davisson May 13 '14 at 13:58
  • @GordonDavisson: Go ahead and make your comment an answer. While the answer of l0b0 pointed me to the cause of the wrong behavior, your comment is the answer for me. – eckes May 14 '14 at 06:45