在帶有多行變數的 shell 腳本中使用 sed

在帶有多行變數的 shell 腳本中使用 sed

我使用 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 inplaceas嘗試先從目前工作目錄gawk載入inplace擴充功能(asinplace或),有人可能已經在其中植入了惡意軟體。隨系統提供的擴展inplace.awk的路徑可能會有所不同,請參閱輸出inplacegawkgawk '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 解決此問題的密切相關答案sedhttp://unix.stackexchange.com/a/60322

相關內容