剪切多个字段文件中的第一个字段

时间:2016-07-04 19:07:26

标签: unix

在下面的文件中:

position1 456754 0/1:170,167:339:99:3370,0,3372:50:99:0.496 ./.:.:.:.:.:.:.:.
position2 456759 0/1:161,162:325:99:3266,0,3215:50:99:0.502 ./.:.:.:.:.:.:.:.

我想得到输出:

position1 456754 0/1 ./.
position2 456759 0/1 ./.

对于第三和第四个字段,我想获得包含/

的第一个字段

如果只有一列,我可以执行以下操作:

cut -d " " -f3 - | cut -f1 -d ":"

粘贴前两列后,这只会给我:

position1 456754 0/1
position2 456759 0/1

我的文件大约有200列,如何对文件中的所有字段进行扩展?

1 个答案:

答案 0 :(得分:1)

你可以制作一个awk单行程序,用于分割包含冒号的字段,并用一个子字段替换那些以空格分隔的字段。像这样:

$ cat inp.txt
position1 456754 0/1:170,167:339:99:3370,0,3372:50:99:0.496 ./.:.:.:.:.:.:.:.
position2 456759 0/1:161,162:325:99:3266,0,3215:50:99:0.502 ./.:.:.:.:.:.:.:.
$ awk '{ for(i=1; i<=NF; i++) { if($i~/:/){split($i,a,":"); $i=a[1] } } } 1' inp.txt
position1 456754 0/1 ./.
position2 456759 0/1 ./.

for循环遍历字段列表。然后,如果任何字段包含冒号,我们将split()字段放入数组(a),并用第一个元素({{1})替换整个字段($i) })。命令字符串末尾的a[1]是“打印此行”的简写,无论是否进行任何替换,都会发生这种情况。

如果你想要一个更简单的awk脚本而牺牲一些CPU,这也应该有效:

1

这简单地消除了$ awk '{ for(i=1; i<=NF; i++) { split($i,a,":"); $i=a[1] } } 1' inp.txt 条件,因此对于每一行上的每个字段,您将用“第一个以冒号分隔的子字段”替换该字段。对于没有冒号的字段,这会将字段替换为自身。

或者,对于不太稳健的解决方案,您可以使用if()

sed

此解决方案读取并替换行内的字符串,而不是以awk的方式解析字段。它可能与awk解决方案完全一样可靠,但可能稍微不那么灵活(例如awk会让你采用不同的子字段,而这种解决方案不会)。

请注意替换命令末尾的$ sed -r -e 's/(:[^ ]*)( |$)/\2/g' inp.txt position1 456754 0/1 ./. position2 456759 0/1 ./. 。这告诉sed“全局”执行此替换,而不仅仅是搜索正则表达式的第一个匹配。

此解决方案使用g选项告诉sed使用扩展正则表达式。如果您使用的是OS X或某些(较旧的)BSD unix,请使用-r选项。在其他unices中,您可能必须将其转换为BRE。

只是两种方法。我肯定会在其他答案中出现更多。