在bash脚本中,右侧的=~和""有什么用?
这是显示行号的 bash 脚本的一部分。我可以理解 getopts 在 bash 中的工作原理,但无法理解第 116 行。if [[ ! " ${FS_OPTIONS[@]} " =~ " $OPTARG " ]]; then
部分。在脚本的早些时候有
#!/usr/bin/env bash
FS_OPTIONS=("ubuntu" "busybox")
while getopts "hsf:" opt; do
case $opt in
f)
if [[ ! " ${FS_OPTIONS[@]} " =~ " $OPTARG " ]]; then
echo "Unsupported filesystem $OPTARG"
echo "Use ubuntu/busybox"
exit -1
else
echo "ok!"
export FILESYSTEM=$OPTARG
fi
;;
esac
done
ckim@chan-ubuntu:~/testbash$ test3.sh -f ubuntu
ok!
ckim@chan-ubuntu:~/testbash$ test3.sh -f busybox
ok!
ckim@chan-ubuntu:~/testbash$ test3.sh -f ubunt.
Unsupported filesystem ubunt.
Use ubuntu/busybox
我将条件行更改为if [[ ! " ${FS_OPTIONS[@]} " =~ $OPTARG ]]; then
,可以看到右侧被视为正则表达式。现在我可以看到
ckim@chan-ubuntu:~/testbash$ test3.sh -f ubunt.
ok!
这是因为删除了“”,并且参数被视为正则表达式。
bash手册说
可以使用额外的二元运算符 =~,其优先级与 == 和 != 相同。使用时,运算符右侧的字符串被视为扩展正则表达式并进行相应匹配(如 regex(3) 中所示)。如果字符串与模式匹配,则返回值为 0,否则为 1。
这在我的问题之前很久了。我的第一个问题是:从我上面观察到的,当模式匹配时,=~ 返回 1。(它之前有!)而不是手册。我错过了什么吗?
我的第二个问题:使用原始文件有哪些用例if [[ ! " ${FS_OPTIONS[@]} " =~ " $OPTARG " ]]; then
?利用正则表达式?因为它有“”,它会将参数作为字符串(不将其作为正则表达式)。带“”的 =~ 有什么用处吗?
回答
你问的具体线路是什么意思?
分解所做的工作[[ ! " ${FS_OPTIONS[@]} " =~ " $OPTARG " ]]
:
" ${FS_OPTIONS[@]} "
在这种情况下,是一个不太清楚的等价物" ${FS_OPTIONS[*]} "
(因为它们之间的通常区别会[@]
扩展到多个词,这在这种情况下是不合法的)。因此,作为${FS_OPTIONS[*]}
,我们将扩展到 中的完整单词列表FS_OPTIONS
,并在它们之间添加一个分隔符(IFS 中的第一个字符,默认为单个空格)。另外,请注意我们在开头和结尾添加了空格(因此我们OPTARG
可以在这些位置匹配,而不仅仅是在中间)。" $OPTARG "
用两边的空格填充我们正在寻找的字符串,因此我们无法匹配子字符串。- 引用右侧的内容,我们正在执行子字符串搜索,因此我们正在检查的内容(
$OPTARG
在开头和结尾添加了空格)是否存在于${FS_OPTIONS[*]}
. - 的
!
反转表达式(改变一个0至1或1至0)的其余的逻辑退出状态。
该语法的一般用途是什么?
-
RHS 上的带引号的字符串充当常规的非锚定子字符串搜索。也就是说,
[[ $foo = "bar" ]]
仅当变量foo
扩展到恰好时才为真bar
,但[[ $foo =~ "bar" ]]
如果变量foo
扩展为包含bar
其内容中的任何位置,则为真。这本身就是一个有用的语义。 -
引用是逐个字符确定的,而不是针对完整字符串。作为如何使用它的示例:
regex_pre='([[:space:]]|^)' literal_string='** match this exactly **' regex_post='([[:space:]]|$)' [[ $foo =~ ${regex_pre}"${literal_string}"${regex_post} ]] # | | | # | | -> unquoted: acts like a regex # | -> quoted: acts like a literal string # -> unquoted: acts like a regex
...
** match this exactly **
仅当它位于字符串的开头或紧接在空格之前,并且在结尾或紧接空格后才匹配,无需为中间的文字字符串编写正则表达式,也无需执行问题中显示的填充空白技巧。