Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a CSV file and I want to truncate it from the third semicolon. For example, if I have this file:

1;foo;bar;baz;x;y;z
2;foo;bar;baz;x;y;z
3;foo;bar;baz;x;y;z

I want to get the following output:

1;foo;bar
2;foo;bar
3;foo;bar

I don't know what kind of Unix command I can use for that. What do you suggest?

Note that this manipulation will be done on a KSH script.

share|improve this question

4 Answers 4

up vote 16 down vote accepted

For the sake of variety, here's another way with cut:

cut -d \; -f -3
share|improve this answer
    
I've never really learned to use cut. :-) –  Omnifarious Nov 13 '12 at 17:56
    
wouldn't it be cut -d \; -f 3? –  gt6989b Nov 13 '12 at 19:34
2  
@gt6989b No, that would print the third field. -3 says to print all fields up to and including the third field. –  Chris Down Nov 13 '12 at 19:41
    
@ChrisDown, thanks, was thinking about -f 1-3, this is a useful shortcut. –  gt6989b Nov 13 '12 at 20:54

This will accomplish what you ask:

awk -F';' '{print $1 ";" $2 ";" $3;}' <input >output

The awk utility is well designed for this task. It can easily cut up individual lines into fields, then manipulate them based on that. The -F';' argument tells awk to use ; as the field separator. The quotes are necessary because the shell would interpret ; as a command separator without them.

The command given to awk to execute for each line (the '{print $1 ";" $2 ";" $3;}' bit) is similarly quoted to keep all the funny characters ({, }, $, " and ; in this case) from being treated specially by the shell and make sure the whole thing is passed to awk as one unit.

And, of course, <input and >output are the redirection directives being given to the shell to redirect the command's input and output from and to a file.

share|improve this answer
    
You need to set OFS, otherwise the ';' will be converted to spaces. –  jordanm Nov 13 '12 at 16:42
    
@jordanm: nod That's one way. The other way is just to put the literal ';' characters in there. :-) I wasn't sure if , would do what I wanted, which is why I had to test it. –  Omnifarious Nov 13 '12 at 16:43
5  
Most of the current awks allow this shorter way: awk -F';' -vOFS=';' 'NF=3'. (With extra precaution: awk -F';' -vOFS=';' 'NF>3{NF=3}1'.) –  manatwork Nov 13 '12 at 16:56
    
@manatwork I like your answer the most. –  jordanm Nov 13 '12 at 17:04
    
@manatwork: Wow. I suppose that makes sense. But it's starting to get perlish in its terse obscurity. –  Omnifarious Nov 13 '12 at 17:57

You can do this using awk, which is not dependent on the shell. You will need to write the output to a temporary file, and then move it on top of the existing one.

awk -F';' 'BEGIN { OFS=";" } { print $1,$2,$3 }' file.txt > newfile.txt
mv newfile.txt file.txt 
share|improve this answer

Not the greatest alternative, just in case you need in-place editing and wish to solve it with sed:

sed -i ':b;s/;[^;]*//3;tb' file.txt
share|improve this answer
2  
Systems that have ksh usually don't have GNU sed, and sed -i is a GNU extension. –  Gilles Nov 13 '12 at 21:58
    
Doh! I checked every used sed command against the POSIX specification before posting, but I forgot the command line option. (By the way, personally I always have a ksh implementation on my Linuxes, either Public Domain Korn Shell or MirBSD™ Korn Shell.) –  manatwork Nov 14 '12 at 6:47

Your Answer

 
discard

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.