如何使用 sed/awk/perl 取代輸入檔中的行

如何使用 sed/awk/perl 取代輸入檔中的行

我正在嘗試替換輸入檔中的路徑。

    #include "../../../Plumed.h"         #### this is old patch in input 

    #include "/usr/local/include/Plumed.h  #### this should be the new path

看到之前回答的問題後(https://stackoverflow.com/questions/11245144/replace-whole-line-containing-a-string-using-sed)。

我試過這個。

    sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg


    perl -i -pe 's/../../../Plumed.h/usr/local/include/Plumed.h/g' ../dist0.xvg

我相信 sed/perl 正在變得困惑,但我不知道如何克服這個問題。任何幫助將不勝感激。

答案1

TL,博士:

使用:

sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg

關於您嘗試的 Sed 命令的一些評論:

sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg
  • -i不可移植,因此看來您正在使用 GNU Sed。

    BSD Sed-i也有一個開關,但備份擴展名是必需的參數,因此要修改文件而不在 BSD Sed 中保存備份需要-i ''.

    -i其他版本的 Sed 可能根本沒有開關。

  • 此處的正規表示式/../../../Plumed.h/包含正規表示式分隔符號的多個副本。

    通常的解決方案是轉義分隔符號:

    /..\/..\/..\/Plumed.h/
    

    然而,關於 Sed 有一個鮮為人知的事實,您可以使用任何s如果您反斜線轉義第一個實例,則為正規表示式分隔符號(而不僅僅是在命令中)。 (好吧,幾乎任何 - 不允許反斜線或換行符。)

    引用POSIX 規範直接地:

    在上下文位址中,建構“ \cBREc”,其中C是除<backslash>或以外的任何字符<newline>,應與“ /BRE/”相同。如果指定的字符C出現在 a 之後<backslash>,則應將其視為該文字字符,該字符不應終止 BRE。例如,在上下文地址“ \xabc\xdefx”中,第二個X代表它自己,因此 BRE 是“ abcxdef”。

    因此,為了避免“傾斜牙籤綜合症”,請注意以下兩個正規表示式是等效的:

    /..\/..\/..\/Plumed.h/
    \:../../../Plumed.h:
    

    請注意,我說的是“等同”不是正確的。這引出了我的下一個觀點,其他答案都忽略了這一點:

  • 正規表示式中的句點 ( .) 代表任何字元

    如果您只想匹配文字句點,則可以使用反斜線轉義句點,或將其貼到字元類別中,如 中[.]

    因此,為了僅匹配文字句點,正規表示式實際上應該更像是:

    \:\.\./\.\./\.\./Plumed\.h:
    

    避免牙籤傾斜就這麼多。

    您也可以使用可以說更具可讀性的形式:

    \:[.][.]/[.][.]/[.][.]/Plumed[.]h:
    
  • c命令改變了整條線,而不僅僅是正規表示式匹配的行部分。

    使用該s命令僅更改一行的一部分。

    值得注意的是,使用該s命令,您不必像在位址中使用備用分隔符號時那樣轉義第一個正規表示式分隔符號(即使對於用作分隔符號的不尋常字元)。

    另外,關於該c命令,值得注意的是,在同一行中包含新文字是c\GNU 擴充且不可移植。


將所有這些放在一起,您可以使用s以下命令:

sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg

或者,如果您想要更明確,您可以使用錨定正規表示式和change命令僅更改整行:

sed -i '\:^#include "\.\./\.\./\.\./Plumed\.h"$:c\#include "/usr/local/include/Plumed.h"' ../dist0.xvg

答案2

如果您將 用作/分隔符sed,解決方案可能是:

sed -i 's/..\/..\/..\/Plumed.h/\/usr\/local\/include\/Plumed.h/g' file

或者,您可以使用與 不同的分隔符/,例如:

sed -i 's:../../../Plumed.h:/usr/local/include/Plumed.h:g' file

另一種方式awk

awk '{ gsub("../../../Plumed.h","/usr/local/include/Plumed.h"); print $0}' file

答案3

這個指令對我有用:

     sed -i 's#include "../../../Plumed.h"#include "/usr/local/include/Plumed.h"#g'

答案4

如果文字中有很多斜杠,請使用感嘆號:

sed -e 's!../../../Plumed.h!/usr/local/include/Plumed.h!'

相關內容