Egrep表达式:从文件中读取时如何取消单引号?

时间:2014-07-24 19:17:52

标签: regex shell grep

我需要使用egrep来获取索引文件中的条目。

为了找到条目,我使用以下命令:

egrep "^$var_name" index

$var_name是从var列表文件中读取的变量:

while read var_name; do
    egrep "^$var_name" index
done < list

其中一个可能的键通常采用以下格式:

$ERROR['SOME_VAR']

我的索引文件格式为:

$ERROR['SOME_VAR'] --> n

其中n是找到变量的行。

问题是$var_name在读取时会自动转义。当我启用调试模式时,我会执行以下命令:

+ egrep '^$ERRORS['\''SELECT_COUNTRY'\'']' index

上面的命令不起作用,因为egrep会尝试解释模式。

如果我不使用扩展版本,使用grepfgrep,该命令仅在我删除^锚点时才有效:

grep -F "$var_name" index # this actually works

问题在于我需要以确保在该行的开头进行匹配。

想法?

2 个答案:

答案 0 :(得分:1)

set -x以shell表示法显示正在执行的命令

您看到的反斜杠成为参数的一部分,它们只是由set -x打印,以可复制的格式显示已执行的命令。

你的问题不是太多逃避,而是太少:正则表达式中的$表示&#34;行尾#34;所以^$ERROR永远不会匹配任何内容。同样,[ ]是一个字符范围,与文字方括号不匹配。

与您的模式匹配的正确正则表达式为^\$ERROR\['SOME VAR'],相当于egrep "^\\\$ERROR\['SOME_VAR']"中的shell参数。

您可以选择解决此问题:

  1. 如果您希望能够在输入文件中使用正则表达式,则需要包含上述的正则表达式转义符,以便您的模式有效。

  2. 如果您希望能够使用任意的文字字符串,请使用可灵活匹配且字面匹配的工具。这需要跳过一些箍,因为遗留原因的UNIX工具非常草率。

  3. 这是一个有awk的人:

    while IFS= read -r line
    do
      export line
      gawk 'BEGIN{var=ENVIRON["line"];} substr($0, 0, length(var)) == var' index
    done < list
    

    它通过环境传递字符串(因为-v很邋))然后从输入的开头按字面意思与字符串匹配。

    这是一个示例调用:

    $ cat script
    while IFS= read -r line
    do
      export line
      gawk 'BEGIN{var=ENVIRON["line"];} substr($0, 0, length(var)) == var' index
    done < list
    
    $ cat list
    $ERRORS['SOME_VAR']
    \E and \Q
    '"'%@#%*'
    
    $ cat index
    hello world
    $ERRORS['SOME_VAR'] = 'foo';
    \E and \Q are valid strings
    '"'%@#%*' too
    etc
    
    $ bash script
    $ERRORS['SOME_VAR'] = 'foo';
    \E and \Q are valid strings
    '"'%@#%*' too
    

答案 1 :(得分:0)

您可以使用printf "%q"

while read -r var_name; do
    egrep "^$(printf "%q\n" "$var_name")" index
done < list

更新:您也可以这样做:

while read -r var_name; do
    egrep "^\Q$var_name\E" index
done < list

此处\Q\E用于在文字字符串之间创建字符串,删除正则表达式符号的所有特殊含义。