6

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.

5 Answers5

19

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

cut -d \; -f -3
Chris Down
  • 125,559
  • 25
  • 270
  • 266
6

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.

Omnifarious
  • 1,322
3

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 
jordanm
  • 42,678
1

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
manatwork
  • 31,277
0

Using Perl

~$ perl -lane '   @F =  split(";"); print join ";", @F[0..2];'  file

Using Raku (formerly known as Perl_6)

$~ raku   -ne 'my @F = .split(";");   put join ";", @F[0..2];'  file   

Here are two answers using Perl and Raku, respectively. Data is read-in linewise using the Perl -lane or Raku -ne non-autoprinting flags. (The difference is Raku performs the -l autochomping by default, however Raku doesn't have the -a flag).

After this, the code is virtually identical. In Raku you have to declare the @F (or @G, or @H array, etc.) with my or our (scope descriptor). Also Raku demands that you indicate what object you're calling split on (.split is short for $_.split meaning the $_ topic variable, which holds individual lines of data as they are read-in).

Finally you either print (Perl) or put (Raku). Raku has print as well, but put adds a newline terminator for you.

Sample Input:

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

Sample Output:

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

Perl References:
https://perldoc.perl.org
https://www.perl.org

Raku References:
https://docs.raku.org
https://raku.org

jubilatious1
  • 3,195
  • 8
  • 17