测试字符串是否包含子字符串

测试字符串是否包含子字符串

我有代码

file="JetConst_reco_allconst_4j2t.png"
if [[ $file == *_gen_* ]];
then
    echo "True"
else
    echo "False"
fi

我测试是否file包含“gen”。输出为“假”。好的!

问题是当我用变量替换“gen”时testseq

file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file == *_$testseq_* ]];
then
    echo "True"
else
    echo "False"
fi

现在输出是“True”。怎么会这样?如何解决这个问题?

答案1

使用=~运算符进行正则表达式比较:

#!/bin/bash
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file =~ $testseq ]];
then
    echo "True"
else
    echo "False"
fi

这样,它将比较其内容是否$file有。$testseq

user@host:~$ ./string.sh
False

如果我改变testseq="Const"

user@host:~$ ./string.sh
True

但是,要小心你吃的东西$testseq。如果其上的字符串以某种方式表示正则表达式(例如[0-9]),则触发“匹配”的机会更高。

参考

答案2

您需要使用$testseq以下方式之一来插入变量:

  • $file == *_"$testseq"_*(这里$testseq视为固定字符串)

  • $file == *_${testseq}_*(这里$testseq被视为一种模式)。

或者_紧随变量名称之后的字符将被视为变量名称的一部分(它是变量名称中的有效字符)。

答案3

file="JetConst_reco_allconst_4j2t.png"
testseq="gen"

case "$file" in
    *_"$testseq"_*) echo 'True'  ;;
    *)              echo 'False'
esac

使用case ... esac是以可移植的方式执行模式匹配的最简单方法之一。它在其他语言中用作“switch”语句(bashzsh、 ,并且ksh93还允许您执行跌倒以各种不兼容的方式)。使用的模式是标准文件名通配模式。

您遇到的问题是由于_变量名称中的字符是有效的。因此,shell 将看到*_$testseq_**_后跟变量值$testseq_*”。该变量$testseq_未定义,因此它将扩展为空字符串,最终得到*_*,它显然与$file您拥有的值匹配。您可能期望得到的True文件名至少$file包含一个下划线。

要正确分隔变量名称,请使用"..."扩展名:*_"$testseq"_*。这会将变量的值用作字符串。您想使用变量的值作为图案*_${testseq}_*改为使用。

另一个快速修复方法是在 的值中包含下划线$testseq

testseq="_gen_"

然后用作*"$testseq"*模式(用于字符串比较)。

答案4

对于测试字符串是否包含子字符串的可移植方法,请使用:

file="JetConst_reco_allconst_4j2t.png";       testseq="gen"

[ "${file##*$testseq*}" ] || echo True Substring is present

或者"${file##*"$testseq"*}"避免解释testseq.

相关内容