Linux
從另一個命令進行管道傳輸時,將原始模式空間限制為匹配的字元串
我有一個文本文件,我想用連字元替換裡面的所有空格
[[
(]]
括號從不嵌套並且總是匹配)。下面是一個例子:$ cat test.txt abc [[foo]] xyz abc [[foo bar]] xyz abc [[foo bar baz]] xyz [[something else]]
所以想要的輸出是:
abc [[foo]] xyz abc [[foo-bar]] xyz abc [[foo-bar-baz]] xyz [[something-else]]
我想我可以使用
sed
匹配括號內的字元串,然後使用e
標誌再次執行結果sed
以進行替換。然而問題在於,不僅匹配的字元串作為命令執行,而且整個模式空間(似乎是整行):$ sed -E 's@(\[\[)(.+)(\]\])@sed -e "s/ /-/g" <<< "\1\2\3"@gpe' test.txt abc sed -e "s/ /-/g" <<< "[[foo]]" xyz sh: 1: Syntax error: redirection unexpected abc sed -e "s/ /-/g" <<< "[[foo bar]]" xyz sh: 1: Syntax error: redirection unexpected abc sed -e "s/ /-/g" <<< "[[foo bar baz]]" xyz sh: 1: Syntax error: redirection unexpected
有沒有辦法將通過
e
標誌執行的內容限制為匹配的字元串?如果沒有,我將如何解決這個問題sed
?
我認為沒有辦法限制
e
修飾符傳遞給外殼的內容。但是你可以做這樣的事情:$ sed -E ':a;s@(.*\[\[)([^][]* [^][]*)(\]\].*)@printf "%s%s%s" "\1" "$(printf "\2" | sed "s/ /-/g")" "\3"@e;ta' test.txt abc [[foo]] xyz abc [[foo-bar]] xyz abc [[foo-bar-baz]] xyz [[something-else]]
請注意,多個替換的處理是通過循環完成的 - 由於匹配的貪婪,它實際上以相反的順序進行替換。
另請注意,可能不支持輸入重定向的
e
用途(因此使用管道等效項)。/bin/sh``<<<``printf "\2" | sed "s/ /-/g"
如果 perl 是一個選項,您可以做一些更接近您的原始意圖的事情,例如:
$ perl -pe 's/(?<=\[\[)(.*?)(?=\]\])/$1 =~ s: :-:rg/ge' test.txt abc [[foo]] xyz abc [[foo-bar]] xyz abc [[foo-bar-baz]] xyz [[something-else]]
由於 perl 提供了一個非貪婪的修飾符,這可以更正常地使用外部替換上的標誌
?
來處理每行的多個替換。g