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

Vie*_*urs 48 string shell-script control-flow variable

我有代码

file="JetConst_reco_allconst_4j2t.png"
if [[ $file == *_gen_* ]];
then
    echo "True"
else
    echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

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

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

file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file == *_$testseq_* ]];
then
    echo "True"
else
    echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

现在输出为“真”。怎么会这样?如何解决问题?

小智 34

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

#!/bin/bash
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file =~ $testseq ]];
then
    echo "True"
else
    echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

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

user@host:~$ ./string.sh
False
Run Code Online (Sandbox Code Playgroud)

如果我改变testseq="Const"

user@host:~$ ./string.sh
True
Run Code Online (Sandbox Code Playgroud)

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

参考

  • 看起来这个答案仅适用于“bash” (3认同)

Rom*_*est 31

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

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

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

或者_紧接在变量名之后的 将作为变量名的一部分(它是变量名中的有效字符)。

  • 什么是便携方式? (2认同)

Kus*_*nda 22

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

case "$file" in
    *_"$testseq"_*) echo 'True'  ;;
    *)              echo 'False'
esac
Run Code Online (Sandbox Code Playgroud)

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

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

要正确分隔变量的名称,请"..."在扩展周围使用:*_"$testseq"_*。这将使用变量的值作为字符串。您是否想将变量的值用作模式,请*_${testseq}_*改用。

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

testseq="_gen_"
Run Code Online (Sandbox Code Playgroud)

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


小智 6

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

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

[ "${file##*$testseq*}" ] || echo True Substring is present
Run Code Online (Sandbox Code Playgroud)

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