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]
例如),则触发“匹配”的机会更高。
参考:
Rom*_*est 31
您需要$testseq
使用以下方式之一插入变量:
$file == *_"$testseq"_*
(此处$testseq
视为固定字符串)
$file == *_${testseq}_*
(这里$testseq
被视为一种模式)。
或者_
紧接在变量名之后的 将作为变量名的一部分(它是变量名中的有效字符)。
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
.