我有一个shell脚本需要检查文件名是否与某个正则表达式匹配,但它总是显示"不匹配".谁能告诉我我的代码有什么问题?
fileNamePattern=abcd_????_def_*.txt
realFilePath=/data/file/abcd_12bd_def_ghijk.txt
if [[ $realFilePath =~ $fileNamePattern ]]
then
echo $realFilePath match $fileNamePattern
else
echo $realFilePath not match $fileNamePattern
fi
Run Code Online (Sandbox Code Playgroud)
Ben*_* W. 10
正则表达式和更简单的"glob"/"wildcard"/"normal" 模式之间存在混淆- 无论你想要什么称呼它们.你正在使用后者,但称之为正则表达式.
如果你想使用一个模式,你应该
分配1时引用它:
fileNamePattern="abcd_????_def_*.txt"
Run Code Online (Sandbox Code Playgroud)
你还不想要任何扩展.
使其与完整路径匹配.这与以下内容不符:
$ mypath="/mydir/myfile1.txt"
$ mypattern="myfile?.txt"
$ [[ $mypath == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Doesn't match!
Run Code Online (Sandbox Code Playgroud)
但在扩展模式后开始*:
$ mypattern="*myfile?.txt"
$ [[ $mypath == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
Run Code Online (Sandbox Code Playgroud)
第一个不匹配,因为它只匹配文件名,但不匹配完整路径.或者,您可以使用第一个模式,但使用参数扩展删除路径的其余部分:
$ mypattern="myfile?.txt"
$ mypath="/mydir/myfile1.txt"
$ echo "${mypath##*/}"
myfile1.txt
$ [[ ${mypath##*/} == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
Run Code Online (Sandbox Code Playgroud)使用==与否=~,如上例所示.您也可以使用更便携=,但由于我们已经使用非POSIX [[ ]]而不是[ ],我们也可以使用==.
如果你想使用正则表达式,你应该:
写下您的图案作为一个:?和*在正则表达式的含义不同; 他们修改了他们的立场,而在glob模式中,他们可以自己站立(参见手册).相应的模式将变为:
fileNameRegex="abcd_.{4}_def_.*.txt"
Run Code Online (Sandbox Code Playgroud)
并可以像这样使用:
$ realFilePath="/data/file/abcd_12bd_def_ghijk.txt"
$ [[ $mypath =~ $fileNameRegex ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
Run Code Online (Sandbox Code Playgroud)保持将正则表达式写入单独参数然后在条件运算符中不加引号使用它的习惯[[ ]],或者转义变得非常混乱 - 它在Bash版本中也更易于移植.
BashGuide有一篇关于Bash中不同类型模式的精彩文章.
请注意,引用您的参数几乎总是一个好习惯.在条件表达式中不需要它[[ ]],并且实际上将右侧的解释抑制为模式或正则表达式.如果你正在使用[ ](它不支持正则表达式和模式),则需要引用以避免特殊字符和空字符串的意外副作用.
1实际上在这种情况下并不完全正确.分配给变量时,手册会说明发生以下情况:
[...]代字号扩展,参数和变量扩展,命令替换,算术扩展和报价删除[...]
即,没有路径名(glob)扩展.虽然在这种情况下使用
fileNamePattern=abcd_????_def_*.txt
Run Code Online (Sandbox Code Playgroud)
与引用的版本一样有效,使用引号可以防止在许多其他情况下出现意外,并且只要模式中有空白就需要使用引号.