Jak zamienić linię w pliku wejściowym za pomocą sed / awk / perl


0

Próbuję zastąpić ścieżkę w pliku wejściowym.

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

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

Po zapoznaniu się z wcześniej udzielonym pytaniem ( https://stackoverflow.com/questions/11245144/replace-whole-line-containing-a-string-using-sed ).

Próbowałem tego.

    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

Wierzę, że sed / perl się myli, ale nie jestem pewien, jak to rozwiązać. Każda pomoc będzie mile widziana.


Na co wcześniej odpowiedziałem na pytanie? Proszę być bardziej konkretnym.
— phk

wspomniany pan !!
— Vikas Dubey,

Odpowiedzi:


0

Jeśli używasz /jako ogranicznika sed, rozwiązaniem może być:

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

lub możesz użyć innego ogranicznika niż /, na przykład ::

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

Innym sposobem jest awk:

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

1

tl, dr:

Posługiwać się:

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

Kilka komentarzy na temat Twojej próby Sed:

sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg
  • -i nie jest przenośny, więc wygląda na to, że używasz GNU Sed.

    BSD Sed ma również -iprzełącznik, ale rozszerzenie kopii zapasowej jest wymaganym argumentem, więc modyfikacja pliku bez zapisywania kopii zapasowej w BSD Sed wymaga -i ''.

    Inne wersje Sed mogą -iw ogóle nie mieć przełącznika.

  • Wyrażenie regularne tutaj /../../../Plumed.h/zawiera wiele kopii ogranicznika wyrażenia regularnego.

    Typowym rozwiązaniem tego problemu jest uniknięcie separatora:

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

    Jest jednak mało znany fakt o Sed, że możesz użyć dowolnego znaku do ogranicznika wyrażenia regularnego (nie tylko w spoleceniu), jeśli odwrócisz ukośnik w pierwszej instancji. (Cóż, prawie każda — ukośnik odwrotny lub nowa linia jest niedozwolona).

    Aby bezpośrednio zacytować specyfikacje POSIX :

    W adresie kontekstowym konstrukcja „ \cBREc”, gdzie c jest dowolnym znakiem innym niż <backslash>lub <newline>, musi być identyczna z „ /BRE/”. Jeżeli znak oznaczony literą c pojawi się po znaku a <backslash>, wówczas będzie uważany za ten literalny znak, który nie powinien kończyć BRE. Na przykład w adresie kontekstowym „ \xabc\xdefx” drugi x oznacza siebie, więc BRE to „ abcxdef”.

    Aby uniknąć „zespołu pochylonych wykałaczek”, zauważ, że następujące dwa wyrażenia regularne są równoważne:

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

    Zauważ, że powiedziałem „odpowiednik” nie poprawne. To prowadzi mnie do następnego punktu, pominiętego w każdej innej odpowiedzi:

  • Kropka ( .) w wyrażeniu regularnym oznacza dowolną postać .

    Jeśli chcesz dopasować tylko literał, możesz albo uciec z kropki odwrotnym ukośnikiem, albo wkleić go do klasy postaci jak w [.].

    Zatem, aby dopasować tylko okresy dosłowne, wyrażenie regularne powinno być bardziej podobne do:

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

    Tyle o unikaniu pochylonych wykałaczek.

    Możesz także użyć prawdopodobnie bardziej czytelnej formy:

    \:[.][.]/[.][.]/[.][.]/Plumed[.]h:
  • cPolecenie zmienia całą linię , a nie tylko część linii dopasowane regex.

    Użyj spolecenia, aby zmienić tylko część linii.

    W szczególności dzięki spoleceniu nie musisz uciekać od pierwszego separatora wyrażenia regularnego (nawet w przypadku niezwykłego znaku używanego jako separator), tak jak w przypadku używania alternatywnego separatora w adresie.

    Co się tyczy cpolecenia, warto wiedzieć, że umieszczenie nowego tekstu w tym samym wierszu co c\rozszerzenie GNU jest nieprzenośne.


Podsumowując, możesz użyć spolecenia w następujący sposób:

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

Lub, jeśli chcesz być jeszcze bardziej wyraźny, możesz użyć zakotwiczonego wyrażenia regularnego i ckomendy hange, aby zmienić tylko całą linię:

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

0

To polecenie działało dla mnie:

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

0

Użyj wykrzyknika, jeśli w tekście jest wiele ukośników:

sed -e 's!../../../Plumed.h!/usr/local/include/Plumed.h!'
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.