入力ファイル内のパスを置き換えようとしています。
#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-including-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
要約:
使用:
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 ''
。Sed の他のバージョンには
-i
スイッチがまったく存在しない場合があります。ここでの正規表現 には、
/../../../Plumed.h/
正規表現区切り文字の複数のコピーが含まれています。この問題の通常の解決策は、区切り文字をエスケープすることです。
/..\/..\/..\/Plumed.h/
しかし、Sedについてはあまり知られていない事実があります。どれでも最初のインスタンスをバックスラッシュ エスケープすると、正規表現の区切り文字として (コマンド内だけでなく
s
) 文字を使用できます。(ほぼすべての文字を使用できますが、バックスラッシュや改行は使用できません。)引用するとPOSIX仕様直接:
コンテキストアドレスでは、構文「
\cBREc
」は、c<backslash>
または以外の文字は<newline>
、「 」と同じになります/BRE/
。cが の後に現れる<backslash>
場合、それはそのリテラル文字とみなされ、BREを終了しないものとする。例えば、コンテキストアドレス「\xabc\xdefx
」では、2番目のバツそれ自体を表すので、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
または、さらに明確にしたい場合は、アンカー正規表現とc
hange コマンドを使用して行全体のみを変更することもできます。
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!'