Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

By pasting into a text editor, I have a textfile gleaned from an online edition of Wilhelm's Yi Jing translation which I now want to split into 64 unequal parts, according to the 64 hexagrams of the Yi Jing. Since the passage for each hexagram begins with some digit(s), a period, and two newlines, the regex should be pretty easy to write. But how do I actually split the textfile into 64 new files according to said regex? Can I pipe a sed command to split? (That just doesn't seem like it would work. It seems like more of a task for perl. But maybe there's a more obvious way that I'm just totally missing.)

share|improve this question
up vote 7 down vote accepted

This would be csplit except that the regex has to be a single line. That also makes sed difficult; I'd go with Perl or Python.

You could see if

csplit foo.txt '/^[0-9][0-9]*\.$/' '{64}'

is good enough for your purposes. (csplit requires a POSIX BRE, so it can't use \d or +, among others.)

share|improve this answer
Thanks, @geekosaur. It worked perfectly, though I had to change it to {63}. – ixtmixilix Jun 26 '11 at 19:47
So, '\.' won't work too? – Vanuan Feb 3 at 10:18

With GNU coreutils, you can use csplit to break a file into regexp-delimited pieces, as shown by geekosaur.

Here's a portable awk script to break a file into pieces. It works by

  • calling getline to deal with the multiline (2-line) separator;
  • setting a variable outfile to the name of the file to print to, when a section header is encountered.
BEGIN {outfile="header.txt"}
    while (/^[0-9]+\.$/) {
        prev = $0; getline;
        if ($0 == "") outfile = prev "txt";
        print prev >outfile
    print >outfile
share|improve this answer
This works in principle, but the section-header of the actual web page data is not as represented by the regex (likewise with geekosaur's answer). The leading nunber. is followed by text which contain a slash /. I'm pretty sure the two newlines ixtmixilix mentioned are the 2 blank lines which precede the numeric identifier and would more specifically identify the header, but as the data on the web page only matches /^[0-9]+\. in the section headers, there is no need to cater for them (in this particular case). thanks; especially for the intro to getline.. PS. can while be if? – Peter.O Jun 27 '11 at 13:58
@fred geekosaur and I went by the description in the question, not by the data on the website. The layout will depend on the HTML rendering engine used to convert to text; the part where this is rendered from a web page is actually irrelevant to the question. ||| while is there in case the input contains 1.\n2.\n\n (where \n are newlines): the 2. must be recognized in the header line. It's not going to occur here, but I support it in my code to make it more general (and match the specification in the question more strictly). – Gilles Jun 27 '11 at 14:20

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.