7

Is it possible to remove the delimiter with csplit? Example:

$ cat in
abc
---
def
---
ghi
$ csplit -q in /-/ '{*}'
$ ls x*
xx00  xx01  xx02
$ head xx*
==> xx00 <==
abc

==> xx01 <==
---
def

==> xx02 <==
---
ghi

Instead of what it did, i.e. split and keep the delimiter, can it be asked to split and remove the delimiter?

That is, the desired output would be this:

$ sed -i '/-/d' xx*
$ head xx*
==> xx00 <==
abc

==> xx01 <==
def

==> xx02 <==
ghi

While it can be done in two steps as above, can it be done in one step?

If it cannot be done with csplit, is there a one-step way that is shorter compared to the two invocations (csplit + sed) above? No preference to a tool used as long as it's reasonably readable.

3 Answers 3

7

Since you seem to be using gnu csplit, it's quite simple:

csplit --suppress-matched infile /PATTERN/ '{*}'

i.e. use --suppress-matched to suppress the lines matching PATTERN.


Per your note, this option is available only with more recent versions of csplit (coreutils ≥ 8.22)

1
  • 1
    Ha! The distribution that I'm on uses coreutils 8.4 (yes, ancient), which looks like it doesn't support that option... It was added in 2013: git.savannah.gnu.org/cgit/coreutils.git/commit/…, so that was included in 8.22. Thanks for the hint though, will become useful with the upgrade I guess! May 10, 2016 at 18:31
2

If you can make do with a string match rather than a regex match

awk 'BEGIN {RS="---\n"; ORS=""} {print > sprintf("xx%02d", NR)}' in

With GNU awk (at least in v4.0.1) it is possible to use a regex for RS e.g.

gawk 'BEGIN {RS="-+\n"; ORS=""} {print > sprintf("xx%02d", NR)}' in
3
  • Thanks +1, I can actually, though is there a short way to do partial string match instead of using RS and supplying the whole one? The separator is like 50 characters... May 5, 2016 at 21:14
  • @levantpied see edit - it may be possible, if you have the GNU version of awk May 5, 2016 at 21:26
  • Nice! I can confirm this works in gawk 3.1.7. May 10, 2016 at 18:34
2
perl -ne 'BEGIN { $fnum=0; open $fh, ">", sprintf "xx%02d", $fnum++ } if (m/-/) { open $fh, ">", sprintf "xx%02d", $fnum++ } else { print $fh $_ }' inputfileorfileshere

Or a similar reopen-into-new-file-on-matching-appropriate-line via awk or whatever.

2
  • Thanks +1, quite long one-liner though :) May 5, 2016 at 21:12
  • +1 , by far the best answer here. Worked better and quicker than csplit for me.
    – Scientist
    Jul 3, 2018 at 13:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .