awk/grep/sed多模式单行匹配:变量替换后无结果求助
解决awk变量匹配无结果的问题
这个问题我碰到过,核心原因是你误用了awk的模式匹配语法!当你写/str1/&&/str2/时,awk会把str1和str2当作字面字符串去匹配,而不是你通过-v传入的变量值,所以自然找不到匹配结果。
修正后的命令
直接用匹配操作符~来引用变量就可以解决问题:
SEARCH1="Corona US" SEARCH2="Infected" DIR="/news" FILES="news_*.txt" \ awk -v str1="$SEARCH1" -v str2="$SEARCH2" ' $0 ~ str1 && $0 ~ str2 { # 第一次匹配该文件时先打印文件名 if (!a[FILENAME]) print FILENAME RS $0 # 后续匹配只打印行内容 else print $0 a[FILENAME]++ }' "${DIR}/${FILES}"
关键知识点解释
- awk的
/pattern/语法是硬编码的字面模式匹配,比如/Corona US/就是直接找包含"Corona US"的行;但/str1/只会找包含"str1"字符串的行,和变量str1无关。 - 要使用变量作为匹配规则,必须用
$0 ~ 变量名的形式:$0代表当前处理的行,~是awk的“匹配”操作符,这样才会用变量里的内容作为匹配规则。
额外优化方案
如果你的搜索词里包含正则特殊字符(比如.、*、+这类),或者你只想做纯字符串匹配(不把搜索词当作正则),可以用index()函数替代,更稳妥:
SEARCH1="Corona US" SEARCH2="Infected" DIR="/news" FILES="news_*.txt" \ awk -v str1="$SEARCH1" -v str2="$SEARCH2" ' index($0, str1) && index($0, str2) { if (!a[FILENAME]) print FILENAME RS $0 else print $0 a[FILENAME]++ }' "${DIR}/${FILES}"
index($0, str)会返回str在当前行中的起始位置(找不到则返回0),这种方式完全是字符串字面匹配,不需要担心正则元字符干扰。
内容的提问来源于stack exchange,提问作者ni_hao
相关产品推荐
相关产品推荐

