为什么我的正则表达式在shell脚本中失败,尽管它在jregex中工作?

时间:2015-10-02 10:20:25

标签: java regex bash shell

我编写了这个简单的脚本,用于在shell脚本中进行匹配

file_name="xyz_abc_diagnostics.wifi2.2015-07-30.12-30-52.tar.gz"
chk_regex=".*\.\d+\-\d+\-\d+\.\d+\-\d+\-\d+.*"
if [[ "$file_name" =~ $chk_regex  ]];then
echo "in obs regex"
else
echo "dont triggered"
fi

我在java中检查了这个正则表达式,这里工作正常。 我的语法是正确的,因为当我使用

.*

工作正常。 对于shell脚本正则表达式测试我使用此站点 http://regexraptor.net/检查它也不匹配,但在https://regex101.com/中使用的是匹配的java正则表达式。 我无法理解为什么它在shell脚本中失败了。 shell脚本正则表达式有什么区别吗?如果是,那么请建议我做什么改变

2 个答案:

答案 0 :(得分:4)

假设所有正则表达式都是相同的是错误的。在这种情况下,bash正则表达式不支持\d。您应该将正则表达式更改为:

chk_regex='\.[0-9]+-[0-9]+-[0-9]+\.[0-9]+-[0-9]+-[0-9]+'

当然,这假设当您说\d时,您不需要超过0到9之间的数字,而不是任何被认为是您所在地区的数字的数字。如果您还要匹配此范围之外的字符,那么[[:digit:]]可能是您想要的,而不是[0-9]

如果您不需要参数扩展,使用'而不是"通常是个好习惯。

我还删除了领先和尾随.*(因为他们没有做任何有用的事情)并取消了-(感谢评论gniourf_gniourf)。

工作示例:

$ file_name="xyz_abc_diagnostics.wifi2.2015-07-30.12-30-52.tar.gz"
$ chk_regex='\.[0-9]+-[0-9]+-[0-9]+\.[0-9]+-[0-9]+-[0-9]+'
$ if [[ "$file_name" =~ $chk_regex  ]];then
> echo "in obs regex"
> else
> echo "dont triggered"
> fi
in obs regex

如您所见,模式匹配,因此if分支被采用。

如评论中所述,您也可以使用globs来匹配此模式:

[[ $file_name = *.+([[:digit:]])-+([[:digit:]])-+([[:digit:]]).+([[:digit:]])-+([[:digit:]])-+([‌​[:digit:]])* ]]

当然,编写时间会更长,但如果您想循环匹配此模式的文件,则可能会使用globs,例如:

for archive in *.+([[:digit:]])-+([[:digit:]])-+([[:digit:]]).+([[:digit:]])-+([[:digit:]])-+([‌​[:digit:]])*
do
    # some stuff
done

请注意,在包含循环的示例中(以及旧版本bash的两个示例中),您需要使用shopt -s extglob启用扩展globs。

答案 1 :(得分:2)

以下是修复方法,使用[0-9]类代替\d并使用{2}限制量词使其更短(实际上,领先/尾随.*是没用,因为你没有使用匹配的字符串,只需检查存在):

#!/bin/bash
file_name="xyz_abc_diagnostics.wifi2.2015-07-30.12-30-52.tar.gz"
chk_regex="(\.[0-9]+(-[0-9]+){2}){2}"
if [[ "$file_name" =~ $chk_regex  ]];then
echo "in obs regex"
else
echo "dont triggered"
fi

请参阅IDEONE demo

结果:in obs regex