在下面的文件中:
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列,如何对文件中的所有字段进行扩展?
答案 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。
只是两种方法。我肯定会在其他答案中出现更多。