如果单词包含特定字母,则 IF 语句返回 true

如果单词包含特定字母,则 IF 语句返回 true

如果单词包含特定字母,我需要一个 if 语句来返回 true。例如:

var="information"
if [ $var contain "i" ]; then
....
else
...
fi

答案1

使用 aswitchcase类似的东西怎么样:

#!/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 字符串,则函数f44s77将报告错误 *output false),例如:

$'\x80abcde'

正如 grep (正则表达式的基本命令)所做的那样(在 utf-8 语言环境中):

$ echo $'\x80abcde' | grep '^.*$'       # no output

$ (LANG=C; echo $'\x80abcde' | grep '^.*$') 
�abcde

相关内容