使用 awk 和 sed 从文件模式到文件执行替换

使用 awk 和 sed 从文件模式到文件执行替换

我的这个有file_13 列,用制表符或空格分隔。

Hhhg_2345_4567_33678    Hhhg_2345_4567_33678    97.0376
Hhhg_2345_4567_33679    Tyre_56576_567_899  70.4077
Hhhg_2345_4567_33680    Jyu_679__89090  79.0189
Hhhg_2345_4567_33681    abc_tyhiulo_89098   97.139
Hhhg_2345_4567_33682    gui_tyu_5678_4567   70.3177
Tyre_56576_567_899  abc_tyhiulo_89098   70.3442
Tyre_56576_567_900  Hhhg_2345_4567_33678    70.4117
Tyre_56576_567_901  Jyu_679__89090  99.9985

我有第二个文件 ( file_2),它们是我的模式,用空格或制表符分隔

Hhhg_2345_4567_33678    EC
Tyre_56576_567_899  CI
Jyu_679__89090  SA

我想要做的是创建一个命令来将 中的字符串替换file_2file_1.所以输出应该是这样的:

EC  EC  97.0376
EC  CI  70.4077
EC  SA  79.0189
EC  abc_tyhiulo_89098   97.139
EC  gui_tyu_5678_4567   70.3177
CI  abc_tyhiulo_89098   70.3442
CI  Hhhg_2345_4567_33678    70.4117

我尝试过这个:

sed '/^[^ ]* [^ ]*$/{H;d;};G;s/ \([^ ]*\)\n.*\n\1 \([[:print:]]*\).*/ \1   \2/;P;d' file2 file1

但它不起作用。

答案1

试试这个 awk 程序。

文件:pattern.awk

# Store "file 2" (the first on command line)
NR == FNR {
    h[$1] = $2
    next
}
# Check "file 1" (the second on command line)
h[$1] != "" {
    $1 = h[$1]
}
h[$2] != "" {
    $2 = h[$2]
}
{
    print
}

使用此命令行(警告,文件顺序非常重要):

awk -f pattern.awk file2 file1

输出将是:

EC EC 97.0376
Hhhg_2345_4567_33679 CI 70.4077
Hhhg_2345_4567_33680 SA 79.0189
Hhhg_2345_4567_33681    abc_tyhiulo_89098   97.139
Hhhg_2345_4567_33682    gui_tyu_5678_4567   70.3177
CI abc_tyhiulo_89098 70.3442
Tyre_56576_567_900 EC 70.4117
Tyre_56576_567_901 SA 99.9985

(不完全是您想要的输出,请参阅 Jim L. 评论)

答案2

这对于宏处理器来说是一项合适的工作m4

宏名称 -名称是字母、数字和字符_(下划线)的任意序列,其中第一个字符不是数字。

m4 <<\EOF
patsubst(include(`file_2'), `\(\S+\)\s+\(\S+\)', `define(`\1', `\2')dnl')dnl
include(`file_1')dnl
EOF

输出:

EC    EC    97.0376
Hhhg_2345_4567_33679    CI  70.4077
Hhhg_2345_4567_33680    SA  79.0189
Hhhg_2345_4567_33681    abc_tyhiulo_89098   97.139
Hhhg_2345_4567_33682    gui_tyu_5678_4567   70.3177
CI  abc_tyhiulo_89098   70.3442
Tyre_56576_567_900  EC    70.4117
Tyre_56576_567_901  SA  99.9985

但如果您需要在排除最后一位数字的模式中进行部分匹配,那么最好使用 GNU AWK:

awk '
NR==FNR && sub(/[0-9]+$/,"", $1) \
    {A[$1] = $2; next}
    {for(i in A) gsub(i"[0-9]+", A[i])}
1' file_2 file_1

输出:

EC    EC    97.0376
EC    CI  70.4077
EC    SA  79.0189
EC    abc_tyhiulo_89098   97.139
EC    gui_tyu_5678_4567   70.3177
CI  abc_tyhiulo_89098   70.3442
CI  EC    70.4117
CI  SA  99.9985

相关内容