我正在尝试在sed中使用shell通配符。以下失败。 (我希望foo
作为输出。)
$ touch foo
$ ls
foo
$ echo *
foo
$ bar=*
$ echo $bar
foo
$ echo "$bar"
*
$ echo replace | sed "s/replace/${bar}/"
*
$ echo replace | sed "s/replace/"${bar}"/"
*
正如预期的那样,倒数第二个命令不会产生foo
,因为${bar}
是(双)引用的。但是,我期望最后一个命令扩展通配符。
bar=$(echo *)
此外,我原本期望在下面进行shell通配符扩展,但不会发生。
$ echo replace | sed s/replace/*/
*
然而,这有效。
$ echo replace | sed s/replace/$(echo *)/
qwe
答案 0 :(得分:3)
您的上一个命令确实尝试扩展通配符,但它失败了。来自man bash
:
Pathname Expansion
After word splitting, unless the -f option has been set, bash
scans each word for the characters *, ?, and [. If one of these
characters appears, then the word is regarded as a pattern, and
replaced with an alphabetically sorted list of file names matching
the pattern.
正如它所说,bash尝试将包含*
的每个单词扩展为匹配的文件名。在您的情况下,它会尝试扩展为以s/replace/
开头的文件名,并且没有此类文件。为了证明这一点:
$ echo "aaaa" | sed "s@a@*@g"
****
$ echo "aaaa" | sed "s@a@"*"@g"
****
$ touch s@a@b@g
$ echo "aaaa" | sed "s@a@*@g"
****
$ echo "aaaa" | sed "s@a@"*"@g"
bbbb
至于问题的解决方案,您可以使用评论中提到的子shell扩展。