Concise and portable “join” on the Unix command-line

前端 未结 9 1901
囚心锁ツ
囚心锁ツ 2020-11-29 00:53

How can I join multiple lines into one line, with a separator where the new-line characters were, and avoiding a trailing separator and, optionally, ignoring empty lines?

相关标签:
9条回答
  • 2020-11-29 01:01

    This sed one-line should work -

    sed -e :a -e 'N;s/\n/,/;ba' file

    Test:

    [jaypal:~/Temp] cat file
    foo
    bar
    baz
    
    [jaypal:~/Temp] sed -e :a -e 'N;s/\n/,/;ba' file
    foo,bar,baz
    

    To handle empty lines, you can remove the empty lines and pipe it to the above one-liner.

    sed -e '/^$/d' file | sed -e :a -e 'N;s/\n/,/;ba'
    
    0 讨论(0)
  • 2020-11-29 01:02

    I had a log file where some data was broken into multiple lines. When this occurred, the last character of the first line was the semi-colon (;). I joined these lines by using the following commands:

    for LINE in 'cat $FILE | tr -s " " "|"'
    do
        if [ $(echo $LINE | egrep ";$") ]
        then
            echo "$LINE\c" | tr -s "|" " " >> $MYFILE
        else
            echo "$LINE" | tr -s "|" " " >> $MYFILE
        fi
    done
    

    The result is a file where lines that were split in the log file were one line in my new file.

    0 讨论(0)
  • 2020-11-29 01:04

    Perl:

    cat data.txt | perl -pe 'if(!eof){chomp;$_.=","}'
    

    or yet shorter and faster, surprisingly:

    cat data.txt | perl -pe 'if(!eof){s/\n/,/}'
    

    or, if you want:

    cat data.txt | perl -pe 's/\n/,/ unless eof'
    
    0 讨论(0)
  • 2020-11-29 01:07

    Simple way to join the lines with space in-place using ex (also ignoring blank lines), use:

    ex +%j -cwq foo.txt
    

    If you want to print the results to the standard output, try:

    ex +%j +%p -scq! foo.txt
    

    To join lines without spaces, use +%j! instead of +%j.

    To use different delimiter, it's a bit more tricky:

    ex +"g/^$/d" +"%s/\n/_/e" +%p -scq! foo.txt
    

    where g/^$/d (or v/\S/d) removes blank lines and s/\n/_/ is substitution which basically works the same as using sed, but for all lines (%). When parsing is done, print the buffer (%p). And finally -cq! executing vi q! command, which basically quits without saving (-s is to silence the output).

    Please note that ex is equivalent to vi -e.

    This method is quite portable as most of the Linux/Unix are shipped with ex/vi by default. And it's more compatible than using sed where in-place parameter (-i) is not standard extension and utility it-self is more stream oriented, therefore it's not so portable.

    0 讨论(0)
  • 2020-11-29 01:10

    Just for fun, here's an all-builtins solution

    IFS=$'\n' read -r -d '' -a data < foo.txt ; ( IFS=, ; echo "${data[*]}" ; )
    

    You can use printf instead of echo if the trailing newline is a problem.

    This works by setting IFS, the delimiters that read will split on, to just newline and not other whitespace, then telling read to not stop reading until it reaches a nul, instead of the newline it usually uses, and to add each item read into the array (-a) data. Then, in a subshell so as not to clobber the IFS of the interactive shell, we set IFS to , and expand the array with *, which delimits each item in the array with the first character in IFS

    0 讨论(0)
  • 2020-11-29 01:11

    I needed to accomplish something similar, printing a comma-separated list of fields from a file, and was happy with piping STDOUT to xargs and ruby, like so:

    cat data.txt | cut -f 16 -d ' ' | grep -o "\d\+" | xargs ruby -e "puts ARGV.join(', ')"
    
    0 讨论(0)
提交回复
热议问题