如何将第二列截断为给定长度


9

输入表格

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

如何只截断第二列?分隔符为TAB,第二列的长度最多为75个字符。


通用一些:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui's

您要截断(第75个字符后删除字符)还是折叠(在另一行上打印字符)?另外,是否应将空格计入75个字符?
terdon

Answers:


7

如果只想打印第二列的前75个字符(包括空格,并假设文件中只有两列),则可以执行以下操作:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

或者,使用GNU sed

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

要么:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

或者,您可以使用fold,告诉它剪切前91个字符(标识符为8,制表符的另外8个字符),然后仅打印第一行:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

如果您的文件可以包含2列以上,而您只想截断第二列,则可以这样做(正如我刚刚注意到的那样,这只是对Stephen答案的重新措词):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

或(请注意,如果第二列的前75个字符可以解释为正则表达式,则此操作会中断):

$ 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命令也是使用GNUism(\t)。
斯特凡Chazelas

@StéphaneChazelas 什么\t是GNUism?认真吗 那么,描述标签的可移植方式是什么?
terdon

1
逐字插入以查看我的答案。在LHS上唯一可识别的转义序列是\n(同样在[...]许多实现中也不是),在RHS上没有。
斯特凡Chazelas

@StéphaneChazelas该死,谢谢。我还添加了一个可以处理多个列的解决方案。
terdon

您的最后perl一个没有任何意义。想想输入类似的实例aba\t.*
斯特凡Chazelas

10

使用awk,使用制表符分割文件,并完整输出第一个字段,并输出第二个字段的前75个字符(最多):

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

fedorqui所指出的,您可以通过替换需要截断的字段来处理具有两个以上字段的文件:

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

substr如有必要,可以通过将它们遍历来将其应用于多个字段。


@Stéphane,在哪些情况下额外;需要?
史蒂芬·基特

POSIX需要它们。现在我不知道在哪里需要它们的任何实现,但是当我要求放宽POSIX要求时,它被gawk维护者拒绝(文档中的所有示例均带有;)。
斯特凡Chazelas

啊,很高兴知道,谢谢!因此,规范和文档比所有实施都严格...
Stephen Kitt,2015年

我至少知道的所有实现(不是很多)。关键是要省略定界符对非标准语法的影响。因此,当前和将来的实现可能并且有权对此加以扼制或引入使用该扩展的扩展(例如,处理一个异常的异常/pattern/ {action} {exception-handling})。鉴于忽略这些;情况相当普遍,因此现在极不可能。
斯特凡Chazelas

4

随身携带/ POSIXly sed

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

或截断每一列:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"

2

如果只有两列:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}表示选择0到75个字符。
.* 是超出char 75的已删除部分。


如果有2 列或更多列:

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* 是超出char 75的已删除部分。


需要注意的是,它假定GNU sedPOSIXLY_CORRECT不在环境..
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.