0

I have a file w/ a thousand lines that looks like this:

9 9 9
9 9 9
9
9 9 9
9 9 9
9

I want to join lines in sets of 3 to produce:

9 9 9 9 9 9 9
9 9 9 9 9 9 9

I thought I'd use sed to replace every 3rd newline with an "X", then join all the lines (:%j in vim), then replace the "X" with new lines.

I tried to use sed to replace every 3rd newline with "X", and it doesn't replace anything:

sed -e "s/\n/X/3" test.txt > test2.txt

I tried \r and \r\n instead of \n, to no avail. It appears sed just is not matching the newline chars. I'm on a Mac. What can I do to match newlines?

Thanks.

  • 2
    `sed` operates a line at a time, and the newline character is not included in the string that it's matching. – Barmar May 19 '23 at 20:48
  • 2
    See https://stackoverflow.com/questions/7852132/sed-join-lines-together for how you join lines together. You don't do it by removing newlines, you do it by concatenating lines – Barmar May 19 '23 at 20:50
  • 4
    This might help: `xargs -d '\n' -n 3 < file` or `paste -d ' ' - - - < file` – Cyrus May 19 '23 at 21:23
  • `pr -3ats' ' test.txt` is another way to join three consecutive lines with a space separator between the lines – Sundeep May 20 '23 at 11:15

2 Answers2

1

With GNU sed. Append the next two lines to sed's pattern space and replace all line breaks with a space:

sed 'N;N;s/\n/ /g;' file

Output:

9 9 9 9 9 9 9
9 9 9 9 9 9 9

From man sed:

N: Append the next line of input into the pattern space

Cyrus
  • 84,225
  • 14
  • 89
  • 153
0

This might work for you (GNU sed):

sed -nE 'H;x;/^(.)(.*)\1(.*)\1(.*)/{s//\2 \3 \4/p;s/.*//};x' file

Turn off implicit printing -n and turn on extended regexps -E.

Append the current line to the hold space.

Swap to the hold space and if that contains 3 newlines, remove them and replace all but the first with spaces and print the result. Then reset (clear) the hold space and return to the current line.

As implicit printing is turned off no further action takes place.

N.B. As at no time has a newline been referred to as \n, this should be applicable to any variety of sed, however the form may need to be adapted i.e. the solution may need to split up or placed in a file and invoked using the -f command line option.

A more programmatic approach, would be:

sed -nE 'H;g;s/./&&/;/^(.)(\1.*){3}/{:a;s/^((.).*)\2/\1 /;ta;s/..//p;s/.*//;h}' file

Another non sed solution :

paste -sd'  \n' file
potong
  • 55,640
  • 6
  • 51
  • 83