Sed

sed 替換字元串如何成為命令的輸出?

  • April 25, 2022

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

要在另一個命令的參數中使用命令的輸出(減去尾隨換行符),您可以使用命令替換,這是 Bourne shell 在 70 年代後期引入的功能。

在 Bourne shell 中,語法是cmd.... 也是如此csh

在現代shsh類似的 shell 中,例如ksh(它來自哪裡)¹、、、、zsh基於的 shell,語法是bash相反的(儘管它們也支持 Bourne 語法以實現向後兼容性)。ash``$(...)

rc-like shell 中,語法是``{cmd…}`

fishshell 中,它(cmd ...)雖然不能在雙引號內使用。從 3.4.0 版本開始,fish還支持$(cmd...)可以在雙引號內使用的 which。

命令替換通常以不同的方式拆分命令的輸出,從而導致傳遞給命令的多個參數,一些(包括大多數 Bourne-like shell)甚至對生成的單詞(!)執行 globbing。這通常可以通過將命令替換放在雙引號內來防止(不是在rc-like shells² 中,也不是在fish< 3.4.0³ 中)。

所以在這裡:

  • 類似 POSIX 的 shell 或fish3.4.0+:
&lt;complex_query&gt; | sed "s,\$,$(grep wow data.txt | cut -d: -f2),"
  • rc- 類似貝殼:
nl = '
'
&lt;complex_query&gt; | sed 's,$,'``($nl){grep wow data.txt | cut -d: -f2},
  • csh/tcsh:
&lt;complex_query&gt; | sed "s,\$,`grep wow data.txt | cut -d: -f2`,"
  • fish< 3.4.0
&lt;complex_query&gt; | sed 's,$,'(grep wow data.txt | cut -d: -f2 | string collect),

現在,請注意&and字元在’命令\的替換部分中是特殊的,因此必須與(此處使用的分隔符)和換​​行符(如果存在換行符)一起轉義(如果可以存在換行符,請注意拆分/為如上所述)。sed``s``\``,``csh``rc

請參閱如何確保插入到 sed 替換中的字元串轉義所有關於此的元字元。

另一種方法是使用perlsed不是不必擔心特殊字元:

&lt;complex_query&gt; | REPL="$(cmd...)" perl -lpe '$_ .= $ENV{REPL}'

(這裡假設一個類似 POSIX 的外殼)

甚至讓 perlcollectcmd的輸出本身(使用它自己的...,並修剪一個尾隨換行符,如果有的話chomp)。

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

¹ksh93和最新版本mksh還支持一種${ ...; }與其他形式不同的形式,但fish不引入 subshel​​l 環境。

² rc-like shell 只有一種類型的引號:'...'它們是強引號(內部不能發生擴展)。您可以通過使用(){cmd ...}`(使用(sep1 sep2){cmd …}`您指定要拆分的分隔符列表的語法,此處為空)來防止拆分,但這也會阻止尾隨換行符修剪。

³ 另請注意,在 csh/tcsh 中,"cmd …"仍會在換行符處拆分。

引用自:https://unix.stackexchange.com/questions/700247