我正在尝试替换
list_file1
中存储的许多模式,这些模式与 data_file1
的字段 2 中的类似数据匹配,然后从 data_file1
完全替换它。
data_file1
应匹配存储在 list_file1
中的大写、小写或大小写模式的组合。
存储在
list_file1
中的模式将包含前导空格、尾随空格和特殊字符。下面给出一些例子。
list_file1
:
AIM TO CONVERT
AIM TO CONVERT
(FAILED)
( FAILED)
\REOCCUR
data_file1
:
UR4289~Deal,( FAILED) Involved~ON654-L
PR4299~Invoc,(failed)closed~BG657-C
UR4980~ AIM TO CONVERT ,JUL51~NN655-V
UR4659~aim To convert -DISSOLVE~MV694-M
预期输出:
UR4289~Deal,Involved~ON654~L
PR4299~Invoc,closed~BG657~C
UR4980~,JUL51~NN655~V
UR4659~-DISSOLVE~MV694~M
到目前为止,Awk 脚本已经准备好了:
awk -F"~" 'NR==FNR{a[$0];next}{for (i in a) {if (index($2,i)) {gsub(tolower(i),"",$0)} {gsub(toupper(i),"",$0)}} print $0}' list_file1 data_file1 >> new_data1
我在这里缺少什么?
您的代码存在几个问题:
index($2,i)
区分大小写,gsub(tolower(i),"",$0)
替换整行而不只是字段 2,gsub(tolower(i),"",$0)
将 tolower(i)
视为正则表达式,而不是文字字符串...你可以尝试:
awk -F'~' -v OFS='~' 'NR == FNR {a[tolower($0)] = length($0); next}
{
for(i in a) {
while(p = index(tolower($2), i)) {
$2 = substr($2, 1, p - 1) substr($2, p + a[i])
}
}
print
}' list_file1 data_file1
注意:这将满足您的要求。但是,如果
list_file1
中的一个字符串是另一个字符串的子部分,则两个字符串中的第一个将首先被删除。示例:AIM TO CONVERT
(带有尾随空格)是 AIM TO CONVERT
(带有前导和尾随空格)的子字符串。如果首先列出 AIM TO CONVERT
(如您的示例所示),UR4980~ AIM TO CONVERT ,JUL51~NN655-V
将替换为 UR4980~ ,JUL51~NN655-V
。如果您希望前导空格也被删除,则必须首先在 AIM TO CONVERT
中列出 list_file1
。
我在这里缺少什么?
gsub
的第一个参数被视为正则表达式并且
AIM TO CONVERT
AIM TO CONVERT
(FAILED)
( FAILED)
\REOCCUR
包含特殊含义的字符,例如括号里,请考虑
echo "ABLE BAKER CHARLIE" | awk -v drop="(B)" '{gsub(drop,"",$0);print $0}'
提供输出
ALE AKER CHARLIE
请注意,即使输入中根本没有括号,B 也被删除了。
我会使用 GNU
AWK
以下方式来解决这个问题,让 file1.txt
内容为
Able
(Baker)
注意:Able 和
file2.txt
内容 be 之前有前导空格
Able~Able~Able # no change - no leading space
Able~ Able~Able # remove
Able~ ABLE~Able # different case remove
Baker~Baker~Baker # no change - no brackets
Baker~(Baker)~Baker # remove
(Baker)~Baker~(Baker) # no change - field different than 2nd
然后
awk 'BEGIN{FS=OFS="~";IGNORECASE=1}FNR==NR{arr[gensub(/(.)/,"[\\1]","g")];next}{for(i in arr){gsub(i,"",$2)};print}' file1.txt file2.txt
提供输出
Able~Able~Able # no change - no leading space
Able~~Able # remove
Able~~Able # different case remove
Baker~Baker~Baker # no change - no brackets
Baker~~Baker # remove
(Baker)~Baker~(Baker) # no change - field different than 2nd
说明:我告知 GNU
AWK
,波形符既是字段分隔符 (FS
) 又是输出字段分隔符 (OFS
),并且它应该以不区分大小写的方式工作 (IGNORECASE)。在处理第一个文件时,我使用gensub
字符串函数将每个字符括在方括号中,这对于没有特殊含义的字符来说并不是绝对必要的,但更容易包围每个字符,这样(Baker)
将被转换为[(][B][a][k][e][r][)]
。对于以下所有文件,我在第二个字段中使用 gsub
以及数组 arr
的每个键。观察到不需要使用 if
,如果不匹配则 gsub
不进行操作。
(在 GNU Awk 5.1.0 中测试)