我有一个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
答案 0 :(得分:9)
正则表达式和更简单的" glob" /"通配符" /"正常"之间存在混淆。 模式 - 无论你想叫什么。你正在使用后者,但称之为正则表达式。
如果你想使用模式,你应该
在分配 1 时引用它:
fileNamePattern="abcd_????_def_*.txt"
你还不想要任何东西扩展。
使其与完整路径匹配。这不匹配:
$ mypath="/mydir/myfile1.txt"
$ mypattern="myfile?.txt"
$ [[ $mypath == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Doesn't match!
但是在将模式扩展为*
之后:
$ mypattern="*myfile?.txt"
$ [[ $mypath == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
第一个不匹配,因为它只匹配文件名,但不匹配完整路径。或者,您可以使用第一个模式,但使用parameter expansion删除路径的其余部分:
$ mypattern="myfile?.txt"
$ mypath="/mydir/myfile1.txt"
$ echo "${mypath##*/}"
myfile1.txt
$ [[ ${mypath##*/} == $mypattern ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
使用==
而非=~
,如上例所示。您也可以使用更具可移植性的=
,但由于我们已经使用非POSIX [[ ]]
而不是[ ]
,我们也可以使用==
如果您想使用正则表达式,您应该:
将您的模式编写为一个:?
和*
在正则表达式中具有不同的含义;他们修改了他们所遵循的内容,而在glob模式中,他们可以自立(见the manual)。相应的模式将成为:
fileNameRegex="abcd_.{4}_def_.*.txt"
可以像这样使用:
$ realFilePath="/data/file/abcd_12bd_def_ghijk.txt"
$ [[ $mypath =~ $fileNameRegex ]] && echo "Matches!" || echo "Doesn't match!"
Matches!
养成将正则表达式写入单独参数然后在条件运算符[[ ]]
中不加引号使用它的习惯,或者转义变得非常混乱 - 它在Bash版本中也更容易移植。
BashGuide有关于Bash中不同类型模式的great article。
请注意,引用参数几乎总是一个好习惯。在[[ ]]
中的条件表达式中不需要它,实际上将右侧的解释抑制为模式或正则表达式。如果您使用[ ]
(它不支持正则表达式和模式),则需要引用以避免特殊字符和空字符串的意外副作用。
1 实际上,在这种情况下,完全完全为真。分配给变量时,manual表示发生以下情况:
[...]代字号扩展,参数和变量扩展,命令替换,算术扩展和引用删除[...]
即,没有路径名(glob)扩展。虽然在这种情况下使用
fileNamePattern=abcd_????_def_*.txt
与引用的版本一样有效,使用引号可以防止在许多其他情况下出现意外,并且只要模式中有空白就需要它。
答案 1 :(得分:2)
使用RegExs而不是通配符:
var splitted = 'http://www.test.info/?id=50&size=40'.split('&');
var urlWithoutAmpersand = splitted[0];
// now urlWithoutAmpersand => 'http://www.test.info/?id=50'
var sizeValue = splitted[1].split('=')[1] * 1;
// now sizeValue => 40
输出:
{ ~ } » 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