Sed

pyenv 安裝說明中的高級 sed 命令

  • February 8, 2022

Pyenv儲存庫,具有以下用於 bash 的 sed 命令:

sed -Ei -e '/^([^#]|$)/ {a \
export PYENV_ROOT="$HOME/.pyenv"
a \
export PATH="$PYENV_ROOT/bin:$PATH"
a \
' -e ':a' -e '$!{n;ba};}' ~/.profile

這是如何工作的?

您顯示的命令將兩行文本添加到您的~/.profile文件中。線條是

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"

它們是與a命令一起添加的(GNU命令對每一行sed使用一次,這是不必要的)。只要正則表達式匹配,就會執行a命令。正則表達式將匹配不以開頭或為空的第一行。這些行附加該觸發行之後。a``^([^#]|$)``#

結尾是一個顯式循環,它通過讀取下一行、列印它並像這樣繼續直到文件結尾,簡單地允許文件的其餘部分保持不變。這避免了在匹配正則表達式並觸發兩個a命令的每一行之後添加兩行文本。

該命令的編寫相當笨拙,因為需要進行一些分析才能弄清楚它應該做什麼。它的要點是,它會~/.profile盡可能早地嘗試在文件中任何初始註釋塊之後的第一行之後插入新內容。它可能應該使用i而不是a在註釋之後添加行,而不是在註釋之後的第一行之後。

就個人而言,我會在腳本末尾添加以下行:

cat >>"$HOME/.profile" <<'PYENV_SETUP_ENDS'
export PYENV_ROOT="$HOME/.pyenv"
PATH=$PYENV_ROOT/bin:$PATH
PYENV_SETUP_ENDS

(注意PATH不需要再次導出。)


使用最近的 GNU awk,您可以使用複制sed命令

awk -i inplace '
   { print }
   !a && (/^[^#]/ || length == 0) {
       print "export PYENV_ROOT=\"$HOME/.pyenv\""
       print "PATH=$PYENV_ROOT/bin:$PATH"
       a = 1
   }' ~/.profile

交換awk程式碼中的兩個塊以獲得在初始註釋塊之後添加的行,而不是在初始註釋塊之後的第一行之後。


相同的 GNUsed命令,但進行了一些清理並使用了更多的空氣進行展示:

sed -i -f - ~/.profile <<'END_SED'
/^#/ b

a \
export PYENV_ROOT="$HOME/.pyenv"\
PATH=$PYENV_ROOT/bin:$PATH

:again
$ ! {
   n
   b again
}
END_SED

a將命令更改i為直接插入到第一個非註釋行之後。

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