0

我有一个读取的数据文件

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 $

我不希望最后一个 No 和 $ 之间有空格

4

5 回答 5

3

像这样,例如:

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

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

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

于 2013-11-11T11:28:47.083 回答
3

除非您有其他一些可能存在匹配风险的标头,否则您No应该使用一些非常简单的东西,例如:

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

这将替换所有No周围有单词边界的字符串。Shell 重定向会将输出存储在一个新文件中。您也可以使用-i开关,但我通常不向新用户推荐它。

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

于 2013-11-11T11:35:22.113 回答
2

使用 awk:

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

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

于 2013-11-11T11:31:37.673 回答
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
于 2013-11-11T11:51:11.937 回答
0

其他awk

awk '$1=="No" {$1="?"} $2=="No" {$2="?"} 1' file
于 2013-11-11T11:33:00.303 回答