【问题标题】:How to match part of a string to a regex in bash?如何将字符串的一部分与bash中的正则表达式匹配?
【发布时间】:2014-09-09 22:55:49
【问题描述】:

我正在使用正则表达式来匹配许多具有相似名称的文件名。请参阅下面的文件。

file1="CGInoimport"
file2="doCGIimport"
file3="donoCGInoimport"
file4="importCGIno"

我正在使用for 循环遍历每个文件变量以检查正则表达式是否匹配。我正在尝试隔离包含单词CGI 的文件名。这是我目前所拥有的。

for (( i=1; i < 5; i++ )) ; do
    if [[ file$i =~ ^CGI$ ]] ; then
        echo "There is a CGI in the name"
    else
        echo "This shouldn't happen"
    fi
done

问题在于每个file,我得到This shouldn't happen。我知道正则表达式有问题,但我不知道如何解决。有什么建议?

如果需要进一步解释,请告诉我。

【问题讨论】:

    标签: regex linux bash shell scripting


    【解决方案1】:

    正则表达式^CGI$ 仅在整个 字符串为CGI 时匹配。如果您想匹配任何子字符串,只需使用CGI

    这是因为在正则表达式中,^ 仅匹配字符串的开头(“锚”匹配开头),$ 仅匹配结尾。也就是说,在这里使用 shell 样式的模式更为传统(使用 = 运算符而不是 =~),并且只需使用通配符来禁用它们的隐式锚定。

    最后,由于要通过变量查找进行查找,因此需要使用变量间接。所以:

    varname=file$i
    if [[ ${!varname} = *CGI* ]]; then
      echo "There is a CGI in the name"
    fi
    

    也就是说,更好的方法是使用数组。所以:

    files=( CGInoimport doCGIimport donoCGInoimport importCGIno )
    for file in "${files[@]}"; do
      [[ $file = *CGI* ]] && echo "There is CGI in the name $file"
    done
    

    ...或者,如果键可以是非数字或不连续的,则为关联数组:

    declare -A files=(
      [file1]=CGInoimport
      [file2]=doCGIimport
      [file3]=donocCGInoimport
      [file4]=importCGIno
    )
    for key in "${!files[@]}"; do
      [[ ${files[file$key]} = *CGI* ]] && echo "There is CGI in $key"
    done
    

    【讨论】:

    • @Alias, ...请参阅补充内容,讨论数组的使用,关联或其他。通常,对于使用间接的任何情况,数组都是更好的替代品。
    • 你知道为什么使用关联数组更适合间接匹配吗?
    • @Alias,使用关联数组的优点是您不太可能遇到命名空间冲突,并且它们更容易安全地填充和操作(不会被诱惑使用 eval )。此外,它们可以有任意键,而不是仅限于也是有效的 shell 变量名的键。也就是说,由于您只是使用数字键,因此在这种特定情况下,您不需要您的数组是关联的;为了完整起见,我展示了它们。
    • 您可以使用${!files[@]} 直接遍历键。
    • @CharlesDuffy 感谢您的帮助,并将记下您的建议。谢谢。
    猜你喜欢
    • 2013-06-29
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 2016-01-04
    • 2010-09-15
    相关资源
    最近更新 更多