Estoy intentando reemplazar una ruta en un archivo de entrada.
#include "../../../Plumed.h" #### this is old patch in input
#include "/usr/local/include/Plumed.h #### this should be the new path
Después de ver la pregunta respondida anteriormente (https://stackoverflow.com/questions/11245144/replace-whole-line-containing-a-string-using-sed).
Intenté esto.
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
Creo que sed/perl se está confundiendo, pero no estoy seguro de cómo solucionarlo. Cualquier ayuda será apreciada.
Respuesta1
tl, dr:
Usar:
sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg
Algunos comentarios sobre su intento de comando Sed:
sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg
-i
no es portátil, por lo que parece que estás usando GNU Sed.-i
BSD Sed también tiene un modificador, pero la extensión de la copia de seguridad es un argumento obligatorio, por lo que para modificar un archivo sin guardar una copia de seguridad en BSD Sed se requiere-i ''
.Es posible que otras versiones de Sed no tengan ningún
-i
interruptor.La expresión regular aquí,
/../../../Plumed.h/
contiene varias copias del delimitador de expresiones regulares.La solución habitual a esto es escapar del delimitador:
/..\/..\/..\/Plumed.h/
Sin embargo, hay un hecho poco conocido sobre Sed, que puedes usarcualquiercarácter para el delimitador de expresiones regulares (no solo en el
s
comando) si se escapa la barra invertida en la primera instancia. (Bueno, casi cualquiera: no se permiten barras invertidas ni nuevas líneas).Para citar elEspecificaciones POSIXdirectamente:
En una dirección de contexto, la construcción "
\cBREc
", dondeCes cualquier carácter distinto de<backslash>
o<newline>
, será idéntico a "/BRE/
". Si el personaje designado porCaparece después de<backslash>
, entonces se considerará que es ese carácter literal, que no dará por terminado el BRE. Por ejemplo, en la dirección de contexto "\xabc\xdefx
", la segundaXse representa a sí mismo, por lo que el BRE es "abcxdef
".Entonces, para evitar el "síndrome del palillo inclinado", tenga en cuenta que las dos expresiones regulares siguientes son equivalentes:
/..\/..\/..\/Plumed.h/ \:../../../Plumed.h:
Tenga en cuenta que dije "equivalente".nocorrecto. Esto me lleva al siguiente punto, omitido en todas las demás respuestas:
Un punto (
.
) en una expresión regular significacualquier personaje.Si desea hacer coincidir solo un punto literal, puede escapar de su punto con una barra invertida o insertarlo en una clase de caracteres como en
[.]
.Por lo tanto, para que coincida sólo con períodos literales, la expresión regular debería ser más parecida a:
\:\.\./\.\./\.\./Plumed\.h:
Esto es suficiente para evitar los palillos inclinados.
También puede utilizar la forma posiblemente más legible:
\:[.][.]/[.][.]/[.][.]/Plumed[.]h:
El
c
comando cambia ellinea completa, no solo la parte de la línea que coincide con la expresión regular.Utilice el
s
comando para cambiar solo una parte de una línea.En particular, con el
s
comando, no tiene que escapar de su primer delimitador de expresiones regulares (incluso para un carácter inusual usado como delimitador) como lo hace cuando usa un delimitador alternativo en una dirección.Además, con respecto al
c
comando, vale la pena saber que incluir el nuevo texto en la misma línea que elc\
es una extensión GNU y no es portátil.
Juntando todo esto, puedes usar el s
comando así:
sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg
O, si quieres ser aún más explícito, puedes usar una expresión regular anclada y el c
comando Hange para cambiar solo la línea completa:
sed -i '\:^#include "\.\./\.\./\.\./Plumed\.h"$:c\#include "/usr/local/include/Plumed.h"' ../dist0.xvg
Respuesta2
Si está utilizando /
como delimitador con sed
, una solución podría ser:
sed -i 's/..\/..\/..\/Plumed.h/\/usr\/local\/include\/Plumed.h/g' file
o puede utilizar un delimitador diferente al de /
, por ejemplo :
:
sed -i 's:../../../Plumed.h:/usr/local/include/Plumed.h:g' file
Otra forma con awk
:
awk '{ gsub("../../../Plumed.h","/usr/local/include/Plumed.h"); print $0}' file
Respuesta3
Este comando funcionó para mí:
sed -i 's#include "../../../Plumed.h"#include "/usr/local/include/Plumed.h"#g'
Respuesta4
Utilice un signo de exclamación si hay muchas barras en el texto:
sed -e 's!../../../Plumed.h!/usr/local/include/Plumed.h!'