Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
    
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
add comment

2 Answers

up vote 2 down vote accepted

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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