我找不到这个问题的答案 - 如果是重复的,我深表歉意。
我/bin/sh
在 BSD 上使用(不是bash!),我正在尝试找出以下 IF 语句的语法。
我有两个组成条款。作为单独的语句编写,它看起来像这样:
if [ "$a" == "y" -o "$a" == "Y" ]; then
if printf '%s' "$b" | grep -qE 'SOME_REGEX'; then
# both conditions met: do stuff
fi
fi
所以我可以使用嵌套if
作为解决方法。
但是我需要什么语法才能将它们整齐地组合成一个“if”语句?
注意:如果这个 shell 允许直接正则表达式匹配比较([ "$a" =~ REGEX" ]
或类似的)而不是 require grep -q
,那么知道这一点很有用,但我仍然想知道如何正确地组合这些子句,因为有一天我肯定会拥有我匹配文件内容而第二条语句类似的情况ls -l "$b" | grep -qE 'SOME_REGEX'
,因此内联正则表达式比较不起作用...:)
答案1
我个人认为这里有一个嵌套语句是可以的if
,尽管我会使用稍微现代化的语法:
if [ "$a" = "y" ] || [ "$a" = "Y" ]; then
if printf '%s' "$b" | grep -qE 'SOME_REGEX'; then
# both conditions met: do stuff
fi
fi
(注意这==
是一个bash
-ism)
将它们组合起来(恕我直言,使其可读性较差):
if [ "$a" = "y" ] || [ "$a" = "Y" ] && printf '%s' "$b" | grep -qE 'SOME_REGEX'; then
# both conditions met: do stuff
fi
为了基本的正则表达式,你可以使用expr
(参见下面是 Stéphane Chazelas 的评论):
if [ "$a" = "y" ] || [ "$a" = "Y" ] && expr "$b" : 'SOME_REGEX' >/dev/null; then
# both conditions met: do stuff
fi
shell/bin/sh
通常不需要[[ ... =~ ... ]]
进行扩展的正则表达式匹配。
关于最后的注释:正则表达式用于跨单行匹配文本。如果将文件名视为文本,则会自动取消任何不是单行文本的文件名的资格,例如包含换行符的文件名。如果您需要对文件名应用正则表达式匹配,请谨慎对待存储在数组 ( $@
in ) 中的名称,或者使用支持谓词/bin/sh
的实现 。find
-regex
文件名通配模式用于匹配文件名。
答案2
请注意,grep
匹配输入的每一行,而不是整个输入,因此通常不适合任意字符串。您可以使用awk
它来代替(注意那是扩展正则表达式类似于grep -E
orbash
的理解[[ string =~ regexp ]]
)。
regexp_match() {
awk 'BEGIN{if (ARGV[1] !~ ARGV[2]) exit(1)}' "$@"
}
if [ "$a" = y ] || [ "$a" = Y ] && regexp_match "$b" REGEXP; then
...
fi
请注意,应避免使用-a
/二元运算符。-o
[
它们已被 POSIX 弃用,并且存在许多问题。例如,在 FreeBSD 上:
$ a='(' /bin/sh -c '[ "$a" = y -o "$a" = Y ]'
[: closing paren expected
答案3
您可以通过连接$a
并向$b
正则表达式添加模式来缩短它
if printf '%s%s\n' "$a" "$b" | grep -qE '^[yY]SOME_REGEX'; then
请注意,grep 是行匹配工具,因此 \n 位于末尾