bash - awk 中的动态正则表达式
问题描述
我有像这样的文本文件
1.txt
AA;00000;
BB;11111;
GG;22222;
2.txt
KK;WW;55555;11111;
KK;FF;ZZ;11111;
KK;RR;YY;11111;
我生成这个3.txt输出
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY
GG;22222;
使用这个 .awk 脚本(我在带有 cmd 的 Windows 中使用它)
#!/usr/bin/awk -f
NR != FNR {
exit
}
{
printf "%s", $0
}
/^BB/ {
o = ""
while (getline tmp < ARGV[2]) {
n = split (tmp,arr,";")
for (i=1; i<=n; i++)
if(!match($0,arr[i]) && !match(o,arr[i]))
o=o arr[i]";"
}
printf "%s", o
}
{
print ""
}
用法是awk -f script.awk 1.txt 2.txt
似乎还可以,但考虑一下这种情况
1.txt
AA;BB;
2.txt
CC;DD;BB;AA;
现在以这种方式替换
AA
替换d(2)
BB
为 替换http://a.o/f/i.p?t=1
CC
为 替换Link
DD
为A_x-y.7z
脚本无法生成3.txt
AA;BB;CC;DD;
或者,使用替换文本无法生成此 3.txt 文本输出
d(2);http://a.o/f/i.p?t=1;Link;A_x-y.7z;
您可以看到像AA
,这样BB
的重复字段已从 3.txt 输出中删除,因为脚本以这种方式工作。
我怀疑这与(...)
被视为 REGEX 分组有关,match()
因为第一个参数是 REGEX 并且通过传递and o 两者都$0
将被视为“动态正则表达式*”awk
解决方案
$ cat tst.awk
BEGIN { FS=OFS=";" }
{ key = $(NF-1) }
NR == FNR {
for (i=1; i<(NF-1); i++) {
if ( !seen[key,$i]++ ) {
map[key] = (key in map ? map[key] OFS : "") $i
}
}
next
}
{ print $0 map[key] }
$ awk -f tst.awk 2.txt 1.txt
AA;00000;
BB;11111;KK;WW;55555;FF;ZZ;RR;YY
GG;22222;
以上只是在数组索引的哈希查找中使用文字字符串,因此它不关心您输入中的字符。如果您希望您的输入被视为文字字符串,则不要在其上使用正则表达式函数或运算符(例如match()
, ) ~
,sub()
只需使用字符串函数/运算符(例如index()
, ==
, substr()
, in
)。
推荐阅读
- scala - 如何使用 Scala 2.11.8 在 Spark REPL 中启用部分统一?
- sql - 语法错误:GROUP BY 子句不能包含聚合或窗口函数
- typescript - 确保接口的类型 T 是实现它的类
- react-native - React Native - 为 useSelector 设置一个简单的变量
- python - 给定 python 中的天、月和小时列表,如何找到最小值?
- ios - 自 Xcode 11.4 以来的状态栏样式问题
- flutter - 如何在 CurvedNavigationBar 上刷新图标颜色
- vue.js - 转到定义不适用于我的项目(vue 和 sass 文件)[visual-studio-code]
- python - 如何将基于索引的公式分配给 sympy 上张量的每个索引位置
- r - r-ggplot2 将图例分为 2 列:geom_sf