4

The file looks like this (one big line):

a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a; etc...... 

Now I want to cut the text and do a line break after every fifth semicolon (;) so it looks like this:

a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; etc.... 

How do I do this?

4 Answers 4

18

With tr and paste

tr ';' '\n' < semicolons | paste -d';' - - - - - 

Tests

$ cat semicolons a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a $ tr ';' '\n' < semicolons | paste -d';' - - - - - a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a a;a;a;a;a 

Both tr and paste are specified in POSIX standard.

To add the required semicolon ; at the end of the lines

tr ';' '\n' < semicolons | paste -d';' - - - - - | sed s/$/\;/ 

Tests

$ tr ';' '\n' < semicolons | paste -d';' - - - - - | sed s/$/\;/ a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; 
2
  • 5
    good one. Alternately tr ';' '\n' < semicolons | paste -sd';;;;\n' Commented Mar 5, 2020 at 15:34
  • @iruvar Good catch ;) Commented Mar 5, 2020 at 15:41
13

Purely using GNU sed substitution:

sed 's/\(\([^;]*;\)\{5\}\)/\1\n/g' 

or without all the escaping backslashes using -E (thanks @JoL):

sed -E 's/(([^;]*;){5})/\1\n/g' 

Example:

$ cat test.txt a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a;a; etc...... $ cat test.txt | sed 's/\(\([^;]*;\)\{5\}\)/\1\n/g' a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a;a; a;a;a;a; etc...... 

Explanation:

  • \([^;]*;\): regex capture group matching all characters up to and including a semi-colon.
  • \(\([^;]*;\)\{5\}\): regex capture group matching five occurrences of the above. In the sed command, this will be matched into \1.
  • s/\(\([^;]*;\)\{5\}\)/\1\n/g: substitute (s/) every occurrence (/g) of the group of five occurrences of all characters up to and including a semicolon (\(\([^;]*;\)\{5\}\)) with itself (\1), but followed by a newline character (\n).
2
  • Also Thanks!!! Solved! Commented Mar 5, 2020 at 15:39
  • 3
    You can skip the backslashes in the pattern by using -r (GNU option) or -E (GNU and POSIX option). I.e. sed -E 's/(([^;]*;){5})/\1\n/g' Commented Mar 6, 2020 at 0:49
5

Sed editor method we place a newline after the 5th semicolon, print upto the newline, remove upto newline, rinse n repeat till you run out of the pattern space.

$ sed -e 's/;/;\n/5;P;D' file 

With Perl, use semicolon as field separator and print in bunches of 5 with semicolons as OFS and an empty field at the end to get the trailing semicolon printed :

$ perl -F\; -lane '$,=";"; print splice(@F, 0, 5), q() while @F; ' file 

Using Awk we look at a bunch of 5 fields and append a semicolon to the first 4 and semicolon + newline to the fifth. Then print the fields with a null separating them:

$ awk -F\; -vOFS= '{ for(i=1; i<=NF; i++) $(i) = $(i) (i%5 ? FS : FS RS) }1' file 
1
  • Upvoted for impressive Sed and Perl solutions (the Awk solution prints an extraneous semi-colon at the very end). Commented Mar 7, 2020 at 20:33
0

I find that while regexes are appropriate for this kind of task, I always do it with text editor macros for the visual help and simplicity.

Using vim, you can

set textwidth=20 

or similarly low and

set wrap 

and if the file really needs editing, a simple macro like

qqf;f;f;f;f;i\n99999@q 

would do it.

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.