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- Contains-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"を設定します。<backslash>、またはを除くすべての文字で、<newline>「」と同じでなければなりません/BRE/。指定された文字の場合後に表示される文字<backslash>は、BREを終了しないリテラル文字として扱われます。たとえば、コンテキストアドレス " \xabc\xdefx"X自分を表しているので、BREは" abcxdef"です。

    したがって、「傾いたつまようじ症候群」を防ぐために、次の2つの正規表現が同じであることに注意してください。

    /..\/..\/..\/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

おすすめ記事