这是一个 bash 4 特定的问题。我对 bash Brace Expressions 有点熟悉,并且我已经阅读了手册,但我不明白它实际上是如何工作的。
我想这与ASCII 表有关,但我不习惯搜索 bash 源代码来确认它,所以我的问题是:
为什么这会echo {G..a}
扩展到
G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a
我有以下问题:我想从字符串中提取括号内的文本(带或不带括号)。我的字符串如下所示:
STR="[1] [2][345] [678 9] foo bar"
我最初想使用 bash 正则表达式和 BASH_REMATCH。我最终使用了以下代码:
regex='\[([^\]]*)\](.*)'
MATCHES=()
STR="[1] [2][345] [678 9] foo bar"
while [[ -n $STR && $STR =~ $regex ]];
do
MATCHES+=("${BASH_REMATCH[1]}")
STR=${BASH_REMATCH[2]}
echo -e "matches: ${BASH_REMATCH[1]} -> ${BASH_REMATCH[2]}"
done
这种工作但我的问题是它只会在括号内捕获一个字符,因此[345]
会导致3
.
我不知道为什么会这样,所以我最终还是使用了 grep 和 PCRE。我目前的解决方案是
regex="\[[^\]]*?\]"
if [[ $(grep -o '\[.*\]' <<< $STR) ]];
then
MATCHES=$(grep -oP "$regex" <<< $STR)
else
echo "No special flags provided."
exit 0
fi
然后我进行一个 for 循环:
for arg in $MATCHES;
do
echo $arg
done
问题是它没有像我希望的那样分隔字段。我使用 hexdump 来找出正确的分隔符:
hexdump -C <<< $MATCHES
令我惊讶的是,这表明分隔符是十六进制0a
的,即LF。这不是问题,因为我知道 for 循环使用 IFS 进行拆分。然后我通过使用将 IFS 设置为 LF IFS=$'\n'
。令我(再次)惊讶的是,0a0a
再次根据 hexdump 将 IFS 的值设置为 。所以那没有用。然后我将 IFS 的值设置为,IFS=''
并且(对于我的第三个惊喜)将值设置为0a
. 但这也不起作用, for 循环没有改变行为。也许我的脚本没有正确设置 IFS 的范围?
我的问题如下:
1) 为什么原来的 bash only 正则表达式方法不起作用?为什么它只捕获一个字符?regex101 dot com 显示了预期的行为,但话又说回来,它不提供 bash 正则表达式模式。
2) 为什么 IFS 设置不能像我预期的那样工作?它添加了一个“额外的”LF,即使我将它设置为空。
3)为什么 IFS 似乎不影响 for 循环?
4)我是否有更简单的方法来解决原始问题([foo] [bar] [foo bar]
从字符串中提取[foo] [bar] 1 asdf[foo bar]
,以我可以循环每个括号对的方式)。
奖金问题!
B) 我对何时应该将变量或表达式括在引号或双引号中感到困惑。我已经阅读了一些关于 globbing 和参数扩展的内容,现在我正在寻找更深入的内容。有什么建议吗?