
我使用 shell 腳本來設定不同類型的虛擬機器。這些腳本通常包含多行變量,需要使用sed
.
如果我像這樣創建它們,一切都很好:
VAR="Config Line1\nConfig Line2\nConfig Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
但這並不會使腳本變得非常可讀,特別是因為文字區塊可能很長。
如果我這樣寫:
VAR="Config Line1
Config Line2
Config Line 3"
sed -i "/MatchingPattern/ a $VAR" somefile
執行腳本時發生錯誤:sed: -e expression #1, char 31: unknown command:
C'`
有沒有辦法使用sed
這樣宣告的變數?
答案1
該指令的標準語法a
為:
sed -e 'a\
first line\
second line\
last line'
BSD(至少 FreeBSD 和 OS/X)sed
去除前導空格, 和需要-e
解決一個錯誤。只要第一行非空,GNUsed
就允許將第一行移到右側之後。a\
因此,您需要預處理輸入:
VAR='content with
multiple lines
some with lead blanks
or even backslash\'
preprocessed_VAR=$(printf '%s\n' "$VAR" |
sed 's/\\/&&/g;s/^[[:blank:]]/\\&/;s/$/\\/')
sed -i -e "/MatchingPattern/a\\
${preprocessed_VAR%?}" somefile
(在 FreeBSD 或 OS/X 上替換-i
為-i ''
)。
在 GNU/Linux 上並使用 GNU shell ( bash
) 或zsh
,您可以這樣做:
sed -i '/MatchingPattern/r /dev/stdin' <<< "$VAR"
這是可行的,因為bash
使用zsh
已刪除的臨時檔案實作here-strings,並且Linux上的/dev/stdin被實作為檔案的符號連結(這意味著它可以被開啟多次,並且每次都在開始時打開)。
這裡你也可以使用 GNUawk
來代替:
(export VAR
gawk -i /usr/share/awk/inplace.awk '{print}; /MatchingPattern/{print ENVIRON["VAR"]}' somefile)
不使用-i inplace
as嘗試先從目前工作目錄gawk
載入inplace
擴充功能(asinplace
或),有人可能已經在其中植入了惡意軟體。隨系統提供的擴展inplace.awk
的路徑可能會有所不同,請參閱輸出inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'
或perl
(-i
來自哪裡):
(export VAR
perl -pi -e '$_ .= "$ENV{VAR}\n" if /MatchingPattern/' somefile)
答案2
這個錯誤是由於sed
附加命令a
在實際的後面需要一個反斜線a
:
使用 GNU sed
:
$ sed "/pattern/a\\$VAR" file.in >file.out
據我所知, BSDsed
只能使用該命令將一行插入文件中a
,除非換行符被正確轉義。
關於如何使用 BSD 解決此問題的密切相關答案sed
:http://unix.stackexchange.com/a/60322