1

I have a text file which contains data in the below format.

1|0|this is test file line1 2|1|this is test file line2 3|1|this is test file line4 

Any line that does not contain | should be appended to the previous line which contains |

Output:

1|0|this is test file line1 2|1|this is test file line2 3|1|this is test file line4 
1
  • 11
    Ok, but we're not a script-writing service Commented Dec 17, 2017 at 15:58

6 Answers 6

4

One way is to use Awk to implement the following algorithm:

  • Track the previous line in prev
  • If the line contains |, and it's not the first line, then print prev. After that, store the current line in prev
  • If the line doesn't contain |, then append it to prev
  • At the end of the script, print prev

For example like this:

awk '/\|/ { if (NR > 1) print prev; prev=$0 } !/\|/ { prev = prev $0 } END { print prev }' input 
0
2

Use | as the field separator: if the line contains a | then the NF variable will be greater than one.

awk -F'|' 'NR > 1 && NF > 1 {print ""} {printf "%s", $0} END {print ""}' file 
1
  • That's close but does not give the required result. Commented Dec 17, 2017 at 16:16
2
awk '/\|/ { if (printed==1) print ""; else printed=1; printf "%s",$0; next; }; { printf " %s",$0 }; END { print ""; }' inputfile 

Or, if you don't care about the leading newline, shorter:

awk '/\|/ { printf "\n%s",$0; next; }; { printf " %s",$0 }; END { print ""; }' inputfile 
1

Awk is my go-to utility for text manipulation:

awk '/\|/ && NR>1 { printf "\n" } !/\|/ && NR>1 { printf " " } { printf $0 } END { printf "\n" }' file 
  1. Print a newline character if the line contains | (but not for the first line):
    /\|/ && NR>1 { printf "\n" }
  2. Otherwise, print a space (but not for the first line):
    !/\|/ && NR>1 { printf " " }
  3. Print the entire line, without a trailing newline character:
    { printf $0 }
  4. Print a newline at the end of the file:
    END { printf "\n" }
0

One more awk:

awk -F'|' 'NR>1{printf prev (NF>1?"\n":" ")}{prev=$0}END{print prev}' file 

Testing

$ cat file1 1|1|this is test file line1 2|2|this is test file line2 3|3|this is test file line3 4|4|this is test file line4 5|5|this is test file line5 6|6|this is test file line6 $ awk -F'|' 'NR>1{printf prev (NF>1?"\n":" ")}{prev=$0}END{print prev}' file1 1|1|this is test file line1 2|2|this is test file line2 3|3|this is test file line3 4|4|this is test file line4 5|5|this is test file line5 6|6|this is test file line6 
0

I would do this using Perl:

perl -e '$f=1;while(<>){chomp;print(($f?"":/\|/?"\n":" ").$_);$f=0}' 

Alternatively, you can use this sed script:

sed -E ':s;N;s/\n([^\n|]*)$/ \1/;bs' 

It is a loop that

  • N reads a line and appends it to the pattern space
  • s/\n([^\n|]*)$/ \1/ if the line in the pattern space does not contain |, replace the newline with a space
  • bs jump back to the :s label

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.