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>
要在另一個命令的參數中使用命令的輸出(減去尾隨換行符),您可以使用命令替換,這是 Bourne shell 在 70 年代後期引入的功能。
在 Bourne shell 中,語法是
cmd...
. 也是如此csh
。在現代
sh
和sh
類似的 shell 中,例如ksh
(它來自哪裡)¹、、、、zsh
基於的 shell,語法是bash
相反的(儘管它們也支持 Bourne 語法以實現向後兼容性)。ash``$(...)
在
rc
-like shell 中,語法是``{cmd…}`在
fish
shell 中,它(cmd ...)
雖然不能在雙引號內使用。從 3.4.0 版本開始,fish
還支持$(cmd...)
可以在雙引號內使用的 which。命令替換通常以不同的方式拆分命令的輸出,從而導致傳遞給命令的多個參數,一些(包括大多數 Bourne-like shell)甚至對生成的單詞(!)執行 globbing。這通常可以通過將命令替換放在雙引號內來防止(不是在
rc
-like shells² 中,也不是在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),
現在,請注意
&
and字元在’命令\
的替換部分中是特殊的,因此必須與(此處使用的分隔符)和換行符(如果存在換行符)一起轉義(如果可以存在換行符,請注意拆分/為如上所述)。sed``s``\``,``csh``rc
請參閱如何確保插入到
sed
替換中的字元串轉義所有關於此的元字元。另一種方法是使用
perl
而sed
不是不必擔心特殊字元:<complex_query> | REPL="$(cmd...)" perl -lpe '$_ .= $ENV{REPL}'
(這裡假設一個類似 POSIX 的外殼)
甚至讓
perl
collectcmd
的輸出本身(使用它自己的...
,並修剪一個尾隨換行符,如果有的話chomp
)。<complex_query> | perl -lpe 'BEGIN{chomp ($repl = `cmd...`)}; $_ .= $repl'
¹
ksh93
和最新版本mksh
還支持一種${ ...; }
與其他形式不同的形式,但fish
不引入 subshell 環境。²
rc
-like shell 只有一種類型的引號:'...'
它們是強引號(內部不能發生擴展)。您可以通過使用(){cmd ...}`(使用
(sep1 sep2){cmd …}`您指定要拆分的分隔符列表的語法,此處為空)來防止拆分,但這也會阻止尾隨換行符修剪。³ 另請注意,在 csh/tcsh 中,
"
cmd …"
仍會在換行符處拆分。