sed 替换字符串如何成为命令的输出?

sed 替换字符串如何成为命令的输出?

下面的 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

在现代的shsh类似的 shell 中,例如基于ksh(来自)的shell ,语法是相反的(尽管它们也支持 Bourne 语法以实现向后兼容性)。zshbashash$(...)

rc-like shell 中,语法是`{cmd...}

fishshell 中,它(cmd ...)不能在双引号内使用。从3.4.0版本开始,fish还支持$(cmd...)可以在双引号内使用which。

命令替换通常会以不同 shell 之间不同的方式分割命令的输出,从而导致传递给命令的多个参数,有些(包括大多数类似 Bourne 的 shell)甚至对结果单词执行通配(!)。通常可以通过将命令替换放在双引号内(而不是在rc类似的 shell² 或fish< 3.4.0³ 中)来防止这种情况。

所以在这里:

  • 类似 POSIX 的 shell 或fish3.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 (此处使用的分隔符)和换行符(如果存在)一起转义(如果可以存在换行符,请注意将/拆分为如上所述)。seds\,cshrc

如何确保插入到“sed”替换中的字符串转义所有元字符关于那个。

另一种方法是使用perlsed不用担心特殊字符:

<complex_query> | REPL="$(cmd...)" perl -lpe '$_ .= $ENV{REPL}'

(这里假设一个类似 POSIX 的 shell)

或者甚至让 perlcollectcmd的输出本身(使用它自己的`...`,并修剪一个尾随换行符(如果有的话chomp))。

<complex_query> | perl -lpe 'BEGIN{chomp ($repl = `cmd...`)}; $_ .= $repl'

ksh93最新版本mksh还支持一种${ ...; }与其他形式不同的形式,但与 in 一样,fish不引入子 shell 环境。

²rc类 shell 只有一种类型的引号:'...'强引号(内部不能发生扩展)。您可以通过使用``(){cmd ...}(使用指定用于拆分的分隔符列表的语法,此处为空)来防止拆分,``(sep1 sep2){cmd ...}但这也会防止尾随换行符修剪。

³ 另请注意,在 csh/tcsh 中,"`cmd ...`"仍然会在换行符处拆分。

相关内容