替换除最后一列之外的所有列中的所有文本

时间:2013-11-11 11:24:28

标签: perl bash shell unix awk

我有一个读取的数据文件

field1 field2 diseased 
discrete discrete   discrete                                                    
                    class
No Yes No 
Yes Yes Yes
No No No

我想在除了带有问号(?)的最后一列之外的所有列中替换否。这只是一个玩具示例,有三列,我有数千列的数据。所以,单独做是没有意义的。前三行是标题,我希望它们不变。所以我希望我的结果是

field1 field2 diseased 
discrete discrete   discrete                                                    
                    class
? Yes No 
Yes Yes Yes
? ? No

我想在不更改文件格式的情况下执行此操作。到目前为止,我可以通过删除最后一列并替换No并再次附加最后一行但丢失格式来实现此目的。还要感谢您的帮助。 在某些情况下,如果有大量的是,而最后一列是否,则最后会添加一些选项卡。命令

cat -e test 

结果

field1 field2 diseased 
discrete discrete   discrete                                                    
                    class
? Yes No$
Yes Yes Yes
? ? No
Yes Yes No $

我不想在最后一个和$

之间留出空格

5 个答案:

答案 0 :(得分:3)

像这样,例如:

$ awk 'BEGIN{OFS=FS="\t"} {for (i=1; i<NF; i++) if ($i=="No") $i="?"}1' a
?       Yes     No 
Yes     Yes     Yes
?       ?       No

它从第1个字段到倒数第二个字段进行检查,并在必要时进行替换。

BEGIN{OFS=FS="\t"}用于将输入和输出字段分隔符设置为选项卡。

答案 1 :(得分:3)

除非你有一些其他标题可以冒险匹配No,否则你应该放弃一些非常简单的东西,例如:

perl -pwe 's/\bNo\b(?!\s*$)/?/g' infile > outfile

将替换围绕它们的字边界的所有No字符串。 Shell重定向将输出存储在新文件中。您也可以使用-i开关,但我通常不建议新用户使用。

使用否定前瞻断言确保它不是该行的最后一个匹配。

答案 2 :(得分:2)

使用awk:

awk -v ccol=3 '{for (i=1; i<=NF; i++) if (i != ccol && $i=="No") $i="?"} 1' OFS='\t' file

您可以传递ccol的任何值,以跳过要替换的列。

答案 3 :(得分:1)

这里我认为不能替换最后一列(必要时可以很容易地进行调整)。

使用awk:

[ ~]$ awk '{for (i=1;i<NF;i++){if ($i=="No"){$i="?"}}; print $0}' test.txt 
field1 field2 diseased 
discrete discrete   discrete                                                    
                    class
? Yes No
Yes Yes Yes
? ? No

使用sed:

[ ~]$ sed "s/No/\?/g; s/\?\ *$/No/g" test.txt 
field1 field2 diseased 
discrete discrete   discrete                                                    
                class
? Yes No
Yes Yes Yes
? ? No

答案 4 :(得分:0)

另一个awk

awk '$1=="No" {$1="?"} $2=="No" {$2="?"} 1' file