I'm trying to build a cherry-picking UI for Git. The output of git log produces lines like this:

e9dfe65  "Alice, 78 minutes ago - Thumbnails are now 300x300" no
3b780ba  "Bob, 3 hours ago - new intro page" no
7ba8120  "Charles, 20 hours ago - add cutoff date for widget timing" no

I want to pass this as arguments to dialog for a checklist:

dialog --checklist "Choose commits to cherry-pick:" 0 0 0 ...

Unfortunately, I can't figure out how to pass the output of git-log as arguments to dialog.

Further arguments to dialog are 3-tuples, such as <commit> <message> <selected>, hence the formatting of git-log above. I can't seem to figure out the expansion.

Some tests:

$ git log ... >temp

$ args="$(cat temp)" ; echo $args[2]
9                                    // WRONG

$ args=`cat temp` ; echo $args[2]              
9                                    // WRONG

$ args=(`cat temp`) ; echo $args[2] 
"Alice,                              // WRONG

Update: The correct result for $args[2] should be Alice, 78 minutes ago - Thumbnails are now 300x300.

link|improve this question

80% accept rate
The reason the last one doesn't work is that the shell treats " in input as a special case to enclose a string that might contain spaces. This behavior is lost when the quotes are read from a program's output — similar to writing \" on the command line. – Daniel Beck Nov 8 '11 at 20:37
It isn't clear to me, what the correct result would be here. – Zoredache Nov 8 '11 at 20:53
@Zoredache Oops, updated. – a paid nerd Nov 8 '11 at 21:09
feedback

2 Answers

You can use the following code to replace all spaces in a line except the first and the last by a non-breaking space character, which the shell doesn't think of as whitespace.

awk '{ x=$2; for(i=3;i<NF;i++){x=x " " $i }; print $1 " " x " " $NF }' temp

To also remove the quotation marks (all quotation marks, unfortunately), use:

awk '{ gsub(/"/, ""); x=$2; for(i=3;i<NF;i++){x=x " " $i }; print $1 " " x " " $NF }' temp

To verify that it works:

$ awk '…' temp | cut -d" " -f1
e9dfe65
3b780ba
7ba8120
$ awk '…' temp | cut -d" " -f2
Alice, 78 minutes ago - Thumbnails are now 300x300
Bob, 3 hours ago - new intro page
Charles, 20 hours ago - add cutoff date for widget timing

Super User breaks my answer. That space character between quotation marks in x=x " " $i is supposed to be 0xC2A0, Unicode code point U+00A0.

link|improve this answer
feedback

a little change to IFS, and some stripping of whitespace, and you can pull the arguments, but it's not exactly a one-liner.

#!/usr/bin/bash

# log format:
# 
# $one  $two               $three
# nnnnn "mmmm mmm mmm mmm" zzzzzz

# save the current IFS, to restore
OLDIFS=$IFS

# set the new IFS to " marks
IFS='"'
cat /tmp/log | while read one two three; do
        # strip the whitespace from $one and $three
        one="$(echo $one | sed -e 's/ //g')"
        three="$(echo $one | sed -e 's/ //g')"
        # print in brackets to see what falls where
        echo "[$one]: [$two] [$three]"
done

# reset the IFS
IFS=$OLDIFS

From there your line is split, maintaining the quoted middle field, and you can do whatever you need with it.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.