将字符串匹配到Bash中的多个globs

时间:2017-05-30 20:03:51

标签: bash

我正在尝试简化我的Bash 4脚本。我正在读取文件中的行,我想排除与某些子字符串相匹配的行:

while read p; do
    if [[ $p != *-ext ]]; then
        if [[ $p != *-backend ]]; then
                if [[ $p != *-vip ]]; then
                    echo $p
                fi
            fi
        fi
    fi
done < $hostsfile

因此,如果该行不以-ext或-backend或-vip结尾,则打印它。什么是一种更简单的方法(单线无法链接&amp;&amp;'s)来实现这一目标?

2 个答案:

答案 0 :(得分:5)

使用扩展模式。这需要启用extglob选项,但默认情况下(暂时)为!= 4.2或更高版本中的[[内的bash运算符的RHS启用。

shopt -s extglob  # if necessary
if [[ $p != *-@(backend|vip|ext) ]]; then

使用正则表达式的等价物将是

if ! [[ $p =~ (backend|vip|ext)$ ]]; then

不需要设置其他选项,但正则表达式不会被隐式锚定,因此您需要匹配字符串的开头,如{{1}在模式中执行,但是 do 需要将字符串的末尾与*-显式匹配。此外,没有与正则表达式运算符匹配(如Perl中的$),因此您需要使用!~并取消命令的退出状态。

答案 1 :(得分:0)

将符合POSIX标准的选项(可移植到/bin/sh)添加到已经存在的非常好的答案中:

case $p in *-backend|*-vip|*-ext) : ;; *) echo "$p" ;; esac

拆分成多行,如下所示:

case $p in
  *-backend|*-vip|*-ext)
    :
    ;;
  *)
    echo "$p"
    ;;
esac

...也就是说,如果任何模式匹配,我们会运行:命令(true的简写),否则我们会echo