Given input of the form
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte
how can I truncate only the second column? The delimiter is TAB and the second column must be at most 75 characters long.
Using awk
, split the file using tabs and output the first field in full and the first 75 characters (at most) of the second:
awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'
As pointed out by fedorqui, you can handle files with more than two fields by replacing the fields you need to truncate:
awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'
You could apply the substr
to multiple fields by looping over them if necessary.
/pattern/ {action} {exception-handling}
for instance). Now that would be extremely unlikely given that omitting those ;
is fairly common.
Commented
May 11, 2015 at 12:08
If you want to print only the first 75 characters of the second column (including spaces, and assuming only two columns in the file), you can do:
$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
Or, with GNU sed
:
$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
Or:
$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
Alternatively, you could use fold
, telling it to cut at the first 91 characters (that's 8 for the identifier and another 8 for the tab), and printing only the first line:
$ fold -w 91 file | head -n1
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
If your file can have more than 2 columns and you only want to truncate the second, you can do (which, as I just noticed, is just a rewording of Stephen's answer):
$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
Or (note that this will break if the first 75 characters of the 2nd column can be interpreted as a regular expression):
$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743 foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
sed
command is also using a GNUism (\t
).
Commented
May 11, 2015 at 11:01
\t
is a GNUism? Seriously? What is the portable way of describing a tab then?
\n
(and again not inside [...]
with many implementations), none on the RHS.
Commented
May 11, 2015 at 11:06
perl
one makes little sense. Think for instance of an input like aba\t.*
Commented
May 11, 2015 at 13:37
Portably/POSIXly with sed
:
tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"
Or to truncate every column:
sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"
If there are only 2 columns:
sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'
{0,75}
means select from 0 up to 75 chars.
.*
is the removed section beyond char 75.
If there are 2 or more columns:
sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file
[^\t]*
is the removed section beyond char 75.
sed
and that POSIXLY_CORRECT
is not in the environment..
Commented
May 11, 2015 at 10:55
awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file