我想在linux shell脚本中有条件地替换一些列。
Mydata是
ID chr pos ver
rs1234 1 12312 b1
rs1245 1 21312 b1
chr1:7576:D 1 22312 b1
rs1002 1 34535 b1
chr1:2434:D 1 34534 b1
MER:1222 1 54645 b1
rs2123 1 45645 b1
如果第一列以“MER”开头或以“D”结尾,我想用“NA”替换第三列。 因此最终文件将如下所示
ID chr pos ver
rs1234 1 12312 b1
rs1245 1 21312 b1
chr1:7576:D 1 **NA** b1
rs1002 1 34535 b1
chr1:2434:D 1 **NA** b1
MER:1222 1 **NA** b1
rs2123 1 45645 b1
答案 0 :(得分:0)
您可以使用awk
完成此操作,如下所示:
# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} print $0}' INPUT > OUTPUT
使用您的样本数据提供以下输出:
ID chr pos ver
rs1234 1 12312 b1
rs1245 1 21312 b1
chr1:7576:D 1 N/A b1
rs1002 1 34535 b1
chr1:2434:D 1 N/A b1
MER:1222 1 N/A b1
rs2123 1 45645 b1
如果要保留格式并且列的宽度是固定的,则可以改为使用printf
语句:
# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} printf("%-As %Bs %Cs %Ds\n",$1,$2,$3,$4)}' INPUT > OUTPUT
用表示所需列宽的整数替换A,B,C和D.例如:
# awk '{if(NR!=1&&($1~/^MER/||$1~/D$/)){$3="N/A"} printf("%-11s %1s %5s %2s\n",$1,$2,$3,$4)}' INPUT > OUTPUT
给出:
ID chr pos ver
rs1234 1 12312 b1
rs1245 1 21312 b1
chr1:7576:D 1 N/A b1
rs1002 1 34535 b1
chr1:2434:D 1 N/A b1
MER:1222 1 N/A b1
rs2123 1 45645 b1
答案 1 :(得分:0)
以下是sed
sed -e 's/\(\(MER:[0-9]\+\|[0-9:]D\)\s\+[0-9]\+\s\+\)[0-9]\+\(.*\)/\1**NA**\3/g' INPUTFILE
生成
ID chr pos ver
rs1234 1 12312 b1
rs1245 1 21312 b1
chr1:7576:D 1 **NA** b1
rs1002 1 34535 b1
chr1:2434:D 1 **NA** b1
MER:1222 1 **NA** b1
rs2123 1 45645 b1
但是awk
可能就是去这里的方式。或者perl。
答案 2 :(得分:0)
这是使用perl one-liner的解决方案:
perl -pe 's/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/' foo.txt
将-i选项添加到perl以直接修改原始文件。
以下是上述示例的更详细分类:
您可以使用s / match / replace / syntax ...
进行搜索和替换s/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/
^^ ^ ^
括号用于捕获要在替换中使用的匹配组。
s/^(MER:.+?|.+?:D)(\s+\d+\s+)(\d+)(.*)$/$1$2**NA**$4/
^_____________^^_________^^___^^__^
$1 $2 $3 $4
只有正则表达式匹配才会发生替换,因此括号中的第一个组确定您的情况下的匹配项。由于您希望以MER:
开头或以:D
结尾,因此|
符号用于表示“或”。
正则表达式是一种强大的搜索和替换方式,并且在许多工具和语言中都受支持。值得在线查找教程以更好地理解这种语法。