演出迟到了?以下非常简单的变体尚未明确提及。我使用case 来检查简单列表,这是一个通用的 Bourne Shell 习惯用法,不依赖任何外部或扩展:
haystack='a b c'
needle='b'
case " $haystack " in (*" $needle "*) :;; (*) false;; esac
- 请注意使用分隔符(此处为:
SPC)来正确分隔模式:" $haystack " 的开头和结尾以及" $needle " 的测试中。
- 如果
$needle 在$haystack 中,则此语句返回true ($?=0),否则返回false。
- 您还可以非常轻松地测试多个
$needle。当有几个类似的情况像
if (haystack.contains(needle1)) { run1() } elif (haystack.contains(needle2)) { run2() } else { run3() }
您也可以将其包装到 case 中:
case " $haystack " in (*" $needle1 "*) run1;; (*" $needle2 "*) run2;; (*) run3;; esac
等等
这也适用于值不包括分隔符本身的所有列表,例如逗号:
haystack=' a , b , c '
needle=' b '
case ",$haystack," in (*",$needle,"*) :;; (*) false;; esac
请注意,如果值可以包含任何内容,包括分隔符序列(NUL 除外,因为 shell 不支持变量中的 NUL,因为您无法将包含 NUL 的参数传递给命令),那么您需要使用数组。数组是 ksh/bashisms,“普通”POSIX/Bourne shell 不支持。 (您可以在 POSIX-Shell 中使用 $@ 来解决此限制,但这与此处所采用的完全不同。)
(*) false 部分可以省略吗?
- 不,因为这是关键的返回值。默认情况下
case 返回true。
- 是的,如果您不需要返回值并将您的处理放在
: 的位置
为什么:;;
- 我们也可以写成
true;;,但我习惯使用:而不是true,因为它更短更快速输入
- 另外,我认为不要写任何不好的做法,因为
case 的默认返回值对每个人来说并不明显。
- 此外,“省略”该命令通常表示“这里忘记了一些东西”。因此,在此处添加多余的“:”清楚地表明“它除了在此处返回 true 之外什么都不做”。
在bash 中,您还可以使用ksh/bashisms,如;& (fallthroug) 或;;& (测试其他模式) 来表达if (haystack.contains(needle1)) { run1(); }; if (haystack.contains(needle2)) { run2(); }
因此通常case 比其他正则表达式结构更易于维护。而且它不使用正则表达式,它只使用 shell 模式,这可能会更快。
可复用功能:
: Needle "list" Seperator_opt
NeedleListSep()
{
if [ 3 -gt $# ];
then NeedleListSep "$1" "$2" " ";
else case "$3$2$3" in (*"$3$1$3"*) return 0;; esac; return 1;
fi;
}
在bash 中,您可以将其简化为
: Needle "list" Seperator_opt
NeedleListSep()
{
local s="${3-" "}";
case "$s$2$s" in (*"$s$1$s"*) return 0;; esac; return 1;
}
这样使用
Test() {
NeedleListSep "$1" "a b c" && echo found $1 || echo no $1;
NeedleListSep "$1" "a,b,c" ',' && echo found $1 || echo no $1;
NeedleListSep "$1" "a # b # c" ' # ' && echo found $1 || echo no $1;
NeedleListSep "$1" "abc" '' && echo found $1 || echo no $1;
}
Test a
Test z
如上所示,这也适用于分隔符为空字符串的退化情况(因此列表的每个字符都是针)。示例:
Test
返回
no
no
no
found
因为空字符串是 abc 的明确部分,以防您的分隔符是空字符串,对吧?
请注意,此功能是公共领域,因为它绝对没有任何东西可以真正受版权保护。