![如果某个模式存在于另一个文件中,如何使用 awk 替换一个文件中的字符串](https://linux22.com/image/186918/%E5%A6%82%E6%9E%9C%E6%9F%90%E4%B8%AA%E6%A8%A1%E5%BC%8F%E5%AD%98%E5%9C%A8%E4%BA%8E%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%EF%BC%8C%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20awk%20%E6%9B%BF%E6%8D%A2%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2.png)
我有一个数据文件A.txt
(字段分隔符 = \t):
Well Well Type Well Name Dye Target
A1 Unknown HIGH-001 FAM ViroFAM
A1 Unknown HIGH-001 HEX ViroHEX
和一个模板文件B.txt
:
kit
Software Version = NOVA_v1
Date And Time of Export = 07/02/2020 13:44:11 UTC
Experiment Name =
Instrument Software Version =
Instrument Type = CFX
Instrument Serial Number =
Run Start Date =
Run End Date =
Run Operator =
Batch Status = VALID
Method = Novaprime
Date And Time of Export,Batch ID,Sample Name,Well,Sample Type,Status,Interpretive Result,Action*,Curve analysis
,taq,205920777.1,A01,Unkn-01
,taq,neg5,A02,Unkn-09
,,,,,,,,,,
*reporting.
我想打印替换with=
第二行中的值,但前提是该模式存在于 的第五列中。B.txt
VIRO_v1
ViroHEX
A.txt
为了做到这一点,我开始了类似的事情:
awk -F'\t' '
FNR==NR{ a[NR]=$2; next }
$1=="Software Version"{ print $0,"VIRO_v1"; next }
1
' B.txt FS=" =" B.txt > result.txt
但我没有弄清楚 的部分A.txt
。你知道该怎么做吗?
答案1
awk -F'\t' '
NR==FNR{ if ($5=="ViroHEX"){ viro=1 } next }
viro && $1=="Software Version"{ $2="VIRO_v1" }
1
' A.txt FS=" = " OFS=" = " B.txt > result.txt
如果第一个字段等于并且出现在第一个文件的第 5 列中的任何位置,则这会将第二个文件中的第二个字段 ( NOVA_v1
)替换。VIRO_v1
Software Version
ViroHEX
我假设第二个文件的字段分隔符是<space>=<space>
(不是制表符)。
答案2
如同贝恩鲍什解,但要更加小心我们实际匹配和插入的内容。
awk -F '\t' '$5 == "ViroHEX" { found = 1; exit } END { exit !found }' A.txt &&
sed '2 s/=.*/= VIRO_v1/' B.txt
这首先用于awk
确定确切的字符串是否ViroHEX
出现在文件中任何行的第五个制表符分隔字段中A.txt
。它不会读取超出必要范围的文件内容,并以稍后用于有条件运行的退出状态退出sed
。
该sed
命令将=
第二行第一个字符中的所有内容替换B.txt
为字符串= VIRO_v1
。
如果A.txt
文件不包含ViroHEX
第五列,则不会生成任何输出。
以下变体始终生成B.txt
文件,可能在第二行完成替换:
if awk -F '\t' '$5 == "ViroHEX" { found = 1; exit } END { exit !found }' A.txt
then
sed '2 s/=.*/= VIRO_v1/'
else
cat
fi <B.txt
如果您不想修改第 2 行,而是想修改 行Software Version = ...
,则将调用中使用的表达式更改为sed
into
s/^\(Software Version = \).*/\1 VIRO_v1/
答案3
以我的愚见,一个更简单的解决方案。不幸的是,除了 awk 之外,它还使用其他工具。
awk '{print $5}' A.txt | grep -q VIROHEX && sed 2s/NOVA/VIRO/ B.txt
&& 之前的部分实现条件,程序sed
替换文件 B.txt 中的文本。
编辑:谢谢 AdminBee 指出我的解决方案是懒惰的。更好的:
awk '{print $5}' A.txt | grep -q VIROHEX && sed '2s/=.*/= VIRO_v1/' B.txt