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?

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;    
| improve this answer | |
  • 5
    good one. Alternately tr ';' '\n' < semicolons | paste -sd';;;;\n' – iruvar Mar 5 at 15:34
  • @iruvar Good catch ;) – Paulo Tomé Mar 5 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).
| improve this answer | |
  • Also Thanks!!! Solved! – Coreta Mar 5 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' – JoL Mar 6 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
| improve this answer | |
  • Upvoted for impressive Sed and Perl solutions (the Awk solution prints an extraneous semi-colon at the very end). – Anthony Geoghegan Mar 7 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.

| improve this answer | |

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.