0

we want to separate each string in csv line to lines

example of line ( could be other line , with the same concept )

machine23,machine094,machine73,machine83

so we try this

echo machine23,machine094,machine73,machine83 |awk -F"," '{for(i=1;i<=NF;i++){printf "%-20s", $i};printf "\n"}'

but we get

machine23   machine094  machine7  machine83 

instead to get the following expected results

machine23
machine094 
machine7 
machine83 

any suggestions?

  • Your solution almost works! The \n needs to be inside the loop; see the latest revision to my answer below. – Adam Katz Aug 28 at 19:26
5
$ echo machine23,machine094,machine73,machine83 | tr ',' '\n'
machine23
machine094
machine73
machine83

or if you really wanted to do it in awk (perhaps because you want to do further processing in awk):

$ echo machine23,machine094,machine73,machine83 | \
  awk -F',' -v OFS='\n' '{$1=$1;$0=$0;print}'
machine23
machine094
machine73
machine83

This uses a neat awk trick where if you change any field (even by setting it equal to itself, as in $1=$) and then set $0=$0, awk will reformat the entire input line - replacing the original field separators (FS, a comma in this case) with the output field separator (OFS, a newline in this case).

  • Not sure what you mean by If you don't reformat it with $0=$0 then you'll have an empty field (and its field separator) in the output.. $0=$0 is to re-split the record into fields, you don't want to do that in this case as it'll combine all 4 fields into 1 since the $1=$1 replaced all FS (,) values with OFSs (\n) so re-splitting the record afterwards won't find any FSs to split on. $0=$0 will never affect the output or any values in the record though, it ONLY re-does field splitting. – Ed Morton Aug 28 at 13:20
  • @EdMorton I was going to say compare the output of blahblahblah, but then I tested it and it seems that either I misremembered it (although i'm certain i've used this trick in the past because there isn't/wasn't any other trivial way of actually deleting - as opposed to setting it to the empty string - a field in awk) or undocumented behaviour has changed in some recent version. – cas Aug 28 at 13:47
  • 2
    Ah, I see what you're getting at - the case you're remembering where you can remove a deleted field is echo 'a b c' | awk '{$2="";$0=$0;$1=$1}1'. First you delete the field contents, then you re-split (and now the 2 blanks between a and c are one FS so 3 fields are now 2), then you recombine $0 changing FSs (including the 2 contiguous blanks) to OFSs (a single blank). – Ed Morton Aug 28 at 13:54
  • 2
    yep, that's it. thanks. – cas Aug 28 at 14:13
1

First, in the spirit of teaching, here's a fixed version of your own logic (wrapped & spaced for legibility):

$ echo machine23,machine094,machine73,machine83 \
    |awk -F"," '{ for (i = 1; i <= NF; i++) { printf "%-20s\n", $i } }'
machine23           
machine094          
machine73           
machine83           

Because you used %-20s, this adds a bit of trailing white space (select the above output to see it), but all I did was move the printf "\n" into the printf inside the for loop.

Since your version had so little white space, here's a code-golfed solution using your logic:

echo machine23,machine094,machine73,machine83|awk -F, '{while(i<NF)print$++i}'

 

Here's a field-agnostic awk solution using global replacement without needing a loop:

$ echo machine23,machine094,machine73,machine83 |awk '{ gsub(/,/,"\n"); print }'
machine23
machine094
machine73
machine83

This mimics the following sed solution:

$ echo machine23,machine094,machine73,machine83 |sed 's/,/\n/g'
machine23
machine094
machine73
machine83

Both of the above simply replace commas with newlines, just like cas's tr solution.

Here's a grep solution:

$ echo machine23,machine094,machine73,machine83 |grep -o '[^,]*'
machine23
machine094
machine73
machine83

This has grep show only (-o) matching non-comma text, with each item on its own line.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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