5

How could I use something like sed to split a file into two so the file containing

eric    shwartz
david    snyder

where the 4 spaces between entries are actually tabs into two files such as:

file1:

eric
david

file2:

shwartz
snyder

So it puts everything after the tab on each line into another file.

15

A solution could be:

awk '{ print $1 > "file1"; print $2 > "file2"}' file 
3
  • AWK > doesn't overwrite the file? – NoOneIsHere Oct 27 '16 at 21:11
  • 1
    @NoOneIsHere, from the POSIX Specifications for Awk: "...if the file of that name is not currently open, it shall be opened, creating it if necessary and...truncating the file. The output then shall be appended to the file. As long as the file remains open, subsequent calls...shall simply append output to the file. The file remains open until the close function...is called...." (or until Awk exits). – Wildcard Oct 28 '16 at 0:37
  • 1
    the op ask to have "everything after the tab on each line" in another file, whereas here you only output $2. You could do, to ensure you get everything after the first tab in file2: sed -e "s/$(printf '\011')/__FIRSTSEP__/" <file | awk -F"__FIRSTSEP__" '{print $1 > "file1" ; print $2>"file2" }' – Olivier Dulac Oct 28 '16 at 14:21
13

Does it have to be one script? If not, you could do this:

cut -f 1 file > file1
cut -f 2 file > file2

cut selects a column(by default separated by tab). -f is a flag which takes a number as an argument, and this number is a number of column.

2
  • 1
    If andreatsh's answer is right, it would probably be better; my solution requires you to read the file twice. – MatthewRock Oct 27 '16 at 13:55
  • 2
    This is better than the accepted answer (apart from the two-pass downside), as it only treats TAB as the delimiter, whereas awk appears to split on any whitespace. (That can be worked around, of course, but then it gets even more complex.) – Darren Cook Mar 19 '20 at 10:32
5

I don't think it can get any simpler than the awk approach, so here's a Perl solution that works for any number of columns, saving each in its own file:

perl -ane 'unless($handles[0]){
            for(1..$#F+1){
                open(my $fh, ">","file$_"); 
                $handles[$_-1] = $fh
            }
           } 
           for my $i (0..$#F){
                print { $handles[$i] } "$F[$i]\n"
           }' file 

Given an input file like this:

$ cat file
foo bar baz bad
foo bar baz bad
foo bar baz bad
foo bar baz bad
foo bar baz bad
foo bar baz bad

The script above will create files file1 through file4 each of which containing the relevant column.


Of course, you can do exactly the same thing in awk, much more simply and elegantly, but where's the fun in that?

awk '{for(i=1;i<=NF;i++){print $i > "file"i}}' file 
2
  • The Awk also handles a sudden increase in the number of fields in the middle of the file. That can be fixed in the perl if we scrap the first loop and put the conditional $handles[$i] opening in the second loop. – Kaz Oct 27 '16 at 20:15
  • @Kaz yeah, but it really isn't worth it. I only posted the perl one for fun, really. Awk is by far the better approach for this sort of thing. – terdon Oct 28 '16 at 10:22
3

Although slightly longer and more complicated here is is a solution using sed. (There is may be a better way but this is how I know to do it.)

sed -e 'h;s/\([^ ]\)\ .*/\1/;w file1' -e 'x;s/.*\ \([^ ]\)/\1/;w file2' file.txt

Explanation

h Save the line in the hold buffer

s/\([^ ]\)\ .*/\1/ Erase everything after the blank space.

w out1 write buffer out to file named file1

I had to start a new expression because the w command would take EVERYTHING after it as the filename to write, lucky for me the hold buffer is still intact between expressions.

x Swap the hold buffer into our working buffer

s/.*\ \(.*\)/\1/Get everything after the first blank space

w out2 write buffer out to a file named file2

0
1

moreutils (available in many distro repos, or http://joeyh.name/code/moreutils/ ) has a few handy utilities, one of which helps here:

pee 'cut -f1 >file1' 'cut -f2 >file2' < file

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.