我正在尝试简化我的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)来实现这一目标?
答案 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
。