奇怪的Bash模式替换行为
此函数奇怪的Bash模式替换行为,bash,Bash,此函数f()应该非常简单,但其工作方式却令人费解: f() { a=(cyan red green blue orange violet) shopt -s extglob echo 1: -${a[@]/!($1)}- echo 2: -${a[@]/!($1)/}- echo 3: -${a[@]/!("$1")/}- echo 4: -"${a[@]/!($1)/}"- echo 5: -${a[@]/!($1)/x}- } echo ORANGE f oran
f()
应该非常简单,但其工作方式却令人费解:
f() {
a=(cyan red green blue orange violet)
shopt -s extglob
echo 1: -${a[@]/!($1)}-
echo 2: -${a[@]/!($1)/}-
echo 3: -${a[@]/!("$1")/}-
echo 4: -"${a[@]/!($1)/}"-
echo 5: -${a[@]/!($1)/x}-
}
echo ORANGE
f orange # ends in e like blue
echo YELLOW
f yellow
输出为(请注意空格/间距):
为什么只搜索单词的最后一个字符?!(在这种情况下,橙色的e
)
预期的输出是orange
,而不仅仅是e
注意:我还希望在某些地方没有看到空白。问题是模式没有被锚定,因此例如对于
orange
,与orange
不匹配的最长字符串是orange
。因此,它被删除,并且只有e
保留在那里。由于无法在bash中指定锚定,因此必须自己创建锚定:
#! /bin/bash
f() {
a=(cyan red green blue orange violet '1 2')
a=("${a[@]/#/|}")
a=("${a[@]/%/|}")
shopt -s extglob
echo ["${a[@]/|!($1)|/-}"]
}
echo ORANGE
f orange # ends in e like blue
echo YELLOW
f yellow
不,壳模式始终隐式地锚定在两端。您的extglob也没有生效。不要将其设置在函数中。感谢您的启发性见解。。我看不到你明显能看到的东西。但是,如果不像您那样实质性地更改接受的值,即预先添加/追加一个分隔符,那么就没有办法锚定该模式了吗?@Robottinosino:我不知道。当我需要进行更复杂的字符串操作时,我通常使用Perl;echo${foo/ga}打印
allitor
@chepner:您可以分别使用/#
和/%
锚定左端或右端,但不能同时使用这两个。正如下面的注释中所暗示的@ormaj,shopt-s extglob
在函数内部不起作用。遵循extglob
的代码编译方式不同,声明时只编译一个函数(一次)。在运行时这样做已经太晚了。这并不是你问题的答案,仍然对这个问题感到困惑…@cdarke:那么为什么我的代码可以工作,但是如果我删除shopt
行,它就不再工作了?有趣的是,你在使用哪个版本的Bash?这里是一样的:OSX:10.8.3;Bash:4.2.42(2)-发行版
和Linux v3.5.0-25-generic Ubuntu 12.10;Bash:4.2.37(1)-发行版
4.2.24这里是x86_64-suse-linux-gnu和4.1.5(1)-发行版(i486 pc linux gnu)
#! /bin/bash
f() {
a=(cyan red green blue orange violet '1 2')
a=("${a[@]/#/|}")
a=("${a[@]/%/|}")
shopt -s extglob
echo ["${a[@]/|!($1)|/-}"]
}
echo ORANGE
f orange # ends in e like blue
echo YELLOW
f yellow