如果单词包含特定字母,我需要一个 if 语句来返回 true。例如:
var="information"
if [ $var contain "i" ]; then
....
else
...
fi
答案1
使用 aswitch
或case
类似的东西怎么样:
#!/bin/sh
v="information"
case $v in
*f*)
echo "found \"f\" in ${v}";;
*)
echo "no match found in ${v}"
esac
exit
请注意,如果针存储在变量中,则引用它很重要,这样它就不会被视为模式:
case $haystack in
*"$needle"*) echo match
esac
如果没有它,如果$needle
是*
或?
例如,它将匹配任何草垛(分别是非空的干草堆)。
无论如何,$needle
不一定是单个字符。它适用于任何字符串。
在许多 shell 中,它甚至适用于任何非空字节序列,即使它们不形成有效字符,但并非所有字节都会分解字符。例如é
,在某些实现中,在以 UTF-8 (0xc3 0xa9) 编码的字符串中可能找不到 0xc3 字节。相反,当语言环境的编码为 BIG5-HKSCS 时,某些 shell 可能会i
在内部找到,其中编码为 0xa3 0x69(与ASCII 一样为 0x69)。ξ
ξ
i
答案2
Bash 的[[ ... ]]
测试了解模式匹配和正则表达式:
当使用
==
and!=
运算符时,运算符右侧的字符串将用作模式并执行模式匹配。使用运算符时=~
,运算符右侧的字符串将作为正则表达式进行匹配。
所以:
s=information
if [[ $s = *i* ]] ; then echo has i ; fi
引用的字符串按字面意思理解:
if [[ $s = "*i*" ]] ; then echo is i between two asterisks ; fi
它知道正则表达式
if [[ $s =~ ^.*i.*$ ]] ; then echo has i ; fi
尽管像往常一样,这也需要不填充整个字符串的匹配:
if [[ $s =~ i ]] ; then echo has i ; fi
答案3
在这种[[ ... ]]
情况下,比较的右侧充当模式。
if [[ $var == *i* ]] ; then
答案4
一种古老的(而且相当便携)的方法是使用 case 语句:
var="information"
case $var in
*i*) echo "An 'i' was found in $var";;
* ) echo "There is no 'i' in $var";;
esac
作为单行函数:
a="information" b="i"
one(){ case $a in (*${b}*) true;; (*) false;; esac; }
并与:
if one; then
echo "Found %b in $a";
else
echo "The character '$b' was not found in the string '$a'"
fi
执行相同测试的其他有效方法是:
two(){ [[ $a == *"$b"* ]] ; } # Using a pattern match.
t33(){ [[ $a =~ "$b" ]] ; } # Extended Regex (ERE) match.
f44(){ [[ $a =~ ^.*"$b".*$ ]] ; } # Using a ERE with limits.
f55(){ [[ ${a//[!"${b}"]} ]] ; } # Removing all non-matching chars.
six(){ [ ! "$a" = "${a%"$b"*}" ] ; } # Using char removal.
s77(){ [[ $a =~ ^.*$ ]] ; } # Testing if string is valid.
所有函数都使用有效的字符串。
对于 10、100、1000、…、1000000(100 万)个字符的字符串,每个函数的时序如下:
Number of characters in the string.
10 100 1000 10000 100000 1000000
one 0.024m 0.036m 0.047m 0.207m 2.117m 25.363m
two 0.028m 0.030m 0.043m 0.179m 2.081m 25.337m
t33 0.044m 0.041m 0.053m 0.151m 1.757m 22.695m
f44 0.064m 0.075m 0.241m 1.864m 19.489m 198.488m
f55 0.055m 0.182m 5.275m 421.886m
six 0.043m 0.057m 0.297m 13.987m
s77 0.056m 0.061m 0.154m 1.201m 12.749m 134.774m
字符数是通过重复字符来构建的。
要测试的字符串是用类似以下内容构建的:
a="$1$(repeat "$2" 10**$k)$3"
该脚本被称为:
$ ./script start a ending
f55
如果处理的字符串长度超过(大约)1000 个字符,该函数会变得非常慢。six
对于长度超过(大约)10000 (10k) 个字符的字符串,也会发生同样的情况。
函数two
对于短字符串来说速度更快,而t33
(regex) 对于较长字符串来说是最好的。
如果运行如下,功能 t33 至 s77 将更改运行时间:
$ LANG=C ./script
一切都变得更快。
有趣的是,如果测试的字符串是无效的 utf-8 字符串,则函数f44
和s77
将报告错误 *output false),例如:
$'\x80abcde'
正如 grep (正则表达式的基本命令)所做的那样(在 utf-8 语言环境中):
$ echo $'\x80abcde' | grep '^.*$' # no output
$ (LANG=C; echo $'\x80abcde' | grep '^.*$')
�abcde