我的输入看起来像这样(制表符分隔文件)
CHROM POS ID REF ALT 76_BRS_AMC_00D2282 c21_BE_MS1038U_BE_MS1038U_c30 93_BRS_MST_DNA17_53119M 94_BRS_MST_DNA17_53120M 100_BRS_BRU_D14_0867
01 12153 rs2454 A G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
01 12154 rs2455 C G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
我想要一个“#”而不是每个列名中的第一个“_”
CHROM POS ID REF ALT 76#BRS_AMC_00D2282 c21#BE_MS1038U_BE_MS1038U_c30 93#BRS_MST_DNA17_53119M 94#BRS_MST_DNA17_53120M 100#BRS_BRU_D14_0867
01 12153 rs2454 A G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
01 12154 rs2455 C G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
我不知道如何使用sed处理表格,我尝试使用awk
awk -F "\t" '/_/ && count < 2 {gsub("_","#");count++} {print $0}'
但它只是替换所有“_”而不仅仅是第一次出现
我想要一个awk或sed解决方案。
(对不起,如果这是一个复制的问题,我没有找到答案)
答案 0 :(得分:1)
sub
将替换第一次出现,因此只需将要修改的记录限制为NR==1
,循环其中的每一列,替换为sub
和print
其余原样:
$ awk 'NR==1{for(i=1;i<=NF;i++)sub(/_/,"#",$i)}1' file
CHROM POS ID REF ALT 76#BRS_AMC_00D2282 c21#BE_MS1038U_BE_MS1038U_c30 93#BRS_MST_DNA17_53119M 94#BRS_MST_DNA17_53120M 100#BRS_BRU_D14_0867
01 12153 rs2454 A G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
01 12154 rs2455 C G 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0
(如果您希望输出也以制表符分隔,您可能需要定义BEGIN{FS=OFS="\t"}
。解释:
$ awk '
#BEGIN{FS=OFS="\t"} # incase you want output tab-delimited also (not in above script)
NR==1 { # process the header record only
for(i=1;i<=NF;i++) # loop every column header
sub(/_/,"#",$i) # replace the first _ with #
}1' file # output
答案 1 :(得分:1)
你可以试试这个gnu sed
sed -E '1s/(\t?[^\t_]+)_([^\t]+)/\1#\2/g' infile
解释:
-E使用扩展正则表达式
1仅在第1行上运行
RE(\ t?[^ \ t _] +)_([^ \ t] +)捕获每一列
(\ t?[^ \ t _] +)抓住第1组
\吨?从可选标签开始(第一列可选)
[^ \ t _] +后跟至少一个不是制表符或_
的字符后跟_
其次是另一组
([^ \ t] +)抓住第2组
所有不是标签的字符
\ 1#\ 2用group1替换列,然后用#后跟group2
g表示对每列进行操作。