下面的 sed 命令有助于将文本添加Hello
到输入的每一行的末尾
<complex_query> | sed "s,$,Hello,"
Output:
myvar1: Hello
myvar2: Hello
我现在希望用 的输出grep wow data.txt | cut -d: -f2
代替Hello
这怎么可能?
下面是我尝试过但不起作用的东西。
<complex_query> | sed "s,$,(grep wow data.txt | cut -d: -f2),"
预期的期望输出:
myvar1: <output of grep wow data.txt | cut -d: -f2 command>
myvar2: <output of grep wow data.txt | cut -d: -f2 command>
答案1
要在另一个命令的参数中使用命令的输出(减去尾随换行符),您可以使用命令替换是 Bourne shell 在 70 年代末引入的一项功能。
在 Bourne shell 中,语法是`cmd...`
.也是如此csh
。
在现代的sh
和sh
类似的 shell 中,例如基于ksh
(来自)的shell ,语法是相反的(尽管它们也支持 Bourne 语法以实现向后兼容性)。zsh
bash
ash
$(...)
在rc
-like shell 中,语法是`{cmd...}
在fish
shell 中,它(cmd ...)
不能在双引号内使用。从3.4.0版本开始,fish
还支持$(cmd...)
可以在双引号内使用which。
命令替换通常会以不同 shell 之间不同的方式分割命令的输出,从而导致传递给命令的多个参数,有些(包括大多数类似 Bourne 的 shell)甚至对结果单词执行通配(!)。通常可以通过将命令替换放在双引号内(而不是在rc
类似的 shell² 或fish
< 3.4.0³ 中)来防止这种情况。
所以在这里:
类似 POSIX 的 shell 或
fish
3.4.0+:<complex_query> | sed "s,\$,$(grep wow data.txt | cut -d: -f2),"
rc
- 类似贝壳:nl = ' ' <complex_query> | sed 's,$,'``($nl){grep wow data.txt | cut -d: -f2},
csh
/tcsh
:<complex_query> | sed "s,\$,`grep wow data.txt | cut -d: -f2`,"
fish
< 3.4.0<complex_query> | sed 's,$,'(grep wow data.txt | cut -d: -f2 | string collect),
现在,请注意&
和字符在命令\
的替换部分中是特殊的,因此必须与with (此处使用的分隔符)和换行符(如果存在)一起转义(如果可以存在换行符,请注意将/拆分为如上所述)。sed
s
\
,
csh
rc
看如何确保插入到“sed”替换中的字符串转义所有元字符关于那个。
另一种方法是使用perl
而sed
不用担心特殊字符:
<complex_query> | REPL="$(cmd...)" perl -lpe '$_ .= $ENV{REPL}'
(这里假设一个类似 POSIX 的 shell)
或者甚至让 perl
collectcmd
的输出本身(使用它自己的`...`
,并修剪一个尾随换行符(如果有的话chomp
))。
<complex_query> | perl -lpe 'BEGIN{chomp ($repl = `cmd...`)}; $_ .= $repl'
和ksh93
最新版本mksh
还支持一种${ ...; }
与其他形式不同的形式,但与 in 一样,fish
不引入子 shell 环境。
²rc
类 shell 只有一种类型的引号:'...'
强引号(内部不能发生扩展)。您可以通过使用``(){cmd ...}
(使用指定用于拆分的分隔符列表的语法,此处为空)来防止拆分,``(sep1 sep2){cmd ...}
但这也会防止尾随换行符修剪。
³ 另请注意,在 csh/tcsh 中,"`cmd ...`"
仍然会在换行符处拆分。