使用Awk匹配两个Shell变量的正则表达式(或逻辑)报错求助
这问题的根源其实和||或者~操作符没关系,是Shell变量传递时没加引号导致的参数拆分问题!你的变量START_TEXT和END_TEXT包含空格,直接写-v start=$START_TEXT的话,Shell会把空格后的部分当成独立的参数传递给awk,让awk误以为text是要读取的文件,这才报了"cannot open file `text'"的错误。
1. 单个Shell变量匹配的正确写法
传递变量时一定要用双引号把变量值包起来,确保空格不会被Shell拆分:
#!/bin/bash START_TEXT="My start text" awk -v start="$START_TEXT" '$0 ~ start { print $2 }' myfile
2. 两个变量用逻辑或匹配的正确写法
写法一:用||连接两个匹配表达式
同样要给传递的变量加双引号:
#!/bin/bash START_TEXT="My start text" END_TEXT="My end text" awk -v start="$START_TEXT" -v end="$END_TEXT" '$0 ~ start || $0 ~ end { print $2 }' myfile
写法二:拼接成单个正则表达式匹配
如果想把两个变量合并成一个正则用|匹配,需要在awk里把变量拼接成正则字符串(注意不能直接写start|end,那样会被当成字面量):
#!/bin/bash START_TEXT="My start text" END_TEXT="My end text" awk -v start="$START_TEXT" -v end="$END_TEXT" '$0 ~ start "|" end { print $2 }' myfile
或者更清晰地加括号明确优先级:
awk -v start="$START_TEXT" -v end="$END_TEXT" '$0 ~ (start "|" end) { print $2 }' myfile
为什么之前的写法会失败?
- 无引号传递变量:比如
-v start=$START_TEXT,Shell会把它拆成-v start=My、start、text三个部分,awk会把最后两个当成输入文件,自然找不到text文件。 - 直接写
$0~/start|end/:这里的start和end是正则里的字面量字符串,不是你传递的awk变量,所以匹配的是内容里的"start"或"end",而不是你的变量值。 - 写
$0~start|end:因为运算符优先级,|的优先级比~高,会被解析成($0 ~ start) | end,这是位运算,完全不符合你的匹配需求,还会导致语法或逻辑错误。
内容的提问来源于stack exchange,提问作者nephewtom
相关产品推荐
相关产品推荐

