我显然缺少一些基本知识,希望能得到一些启发。我看过很多关于查看 bash 命令行参数是否与字符串匹配的帖子。但是,我无法让事情按我预期的方式运行。
这是我现在的my.script.sh
#!/bin/bash
if [[ "$*" =~ .*\.("Rmd"|"tex")$ ]]; then
echo "Here"
else
echo "there"
fi
我希望当任何命令行参数以“.Rmd”或“.tex”结尾时打印“Here”。但是,只有当最后的参数以“.Rmd”或“.tex”结尾。
例如
$ my.script.sh test.Rmd
Here
$ my.script.sh test.Rmd test.txt
there
$ my.script test.txt test.Rmd
Here
我尝试用“$@”代替“$*”,但无济于事。
我如何获得所需的行为(最好不使用 for 循环)?
答案1
Here
仅当最后一个参数以.Rmd
或结尾时才会打印.tex
。
因为"$*"
将所有参数连接成一个字符串(例如test.Rmd test.txt
),然后$
在正则表达式中只能匹配此字符串。
如果您的正则表达式尝试匹配空格字符作为字符串末尾的替代,那么它会起作用;但是它将无法区分单个参数和test.Rmd test.txt
由单独参数产生的字符串test.Rmd
,并且test.txt
."$*"
会给您一个不包含有关参数之间边界的确切信息的字符串。
在某些情况下可能"$*"
有用,但在许多情况下这并不是您真正想要的。例如,"$*"
测试“任何参数”可能会给您带来意想不到的结果,即使您想要匹配,也不一定在最后。示例:
[[ "$*" =~ "lo wo" ]]
Hello world
作为参数将按预期匹配。但是(使用默认值$IFS
)两个连续的参数Hello
和world
也将匹配;但它们都不包含lo wo
。
循环确实是一种完成您想做的事情的明智方法。
#!/bin/bash
message="there"
for a do
if [[ "$a" =~ \.(Rmd|tex)$ ]]; then
message="Here"
break
fi
done
echo "$message"
注意我从你的模式中删除了前导.*
。一般来说,如果模式与字符串的任何部分匹配,它就会匹配;因此你需要一个明确的^
(或) 来锚定到字符串的开头(或结尾);但这意味着如果你不想锚定,$
你不需要前导(或尾随) (如果你打算稍后使用,你仍然可能需要)。.*
.*
$BASH_REMATCH