2012-01-21 35 views
12

Tengo un documento de texto plano, que quiero compilar dentro de LaTeX. Sin embargo, a veces tiene los caracteres "#", "$", "%", "&" y "_". Para compilar correctamente en LaTeX, primero debo reemplazar estos caracteres por "#", "\ $", "\%", "\ &" y "_". He utilizado esta línea en sed:

sed -i 's/\#/\\\#/g' ./file.txt 
sed -i 's/\$/\\\$/g' ./file.txt 
sed -i 's/\%/\\\%/g' ./file.txt 
sed -i 's/\&/\\\&/g' ./file.txt 
sed -i 's/\_/\\\_/g' ./file.txt 

Es esto correcto?

Desafortunadamente, el archivo es demasiado grande para abrirlo en cualquier software de GUI, por lo que es difícil verificar si mi línea sed es correcta con un editor de texto. He intentado buscar con grep, pero la búsqueda no funciona como se espera (por ejemplo, a continuación, he buscado todas las líneas que contienen "$"):

grep "\$" file.txt 
  • ¿Cuál es la mejor manera de poner "\" delante de estos personajes?
  • ¿Cómo puedo usar grep para verificar con éxito las líneas con los reemplazos?
+1

¿Puede garantizar que no tiene ningún carácter especial del que YA se haya escapado? – wim

+1

¿Cómo funciona grep, si no es el esperado? – chepner

+0

Cuando ejecuto 'grep" \ $ "file.txt' parece estar imprimiendo todo o casi todo. No sé por qué está imprimiendo tanto texto, ya que "$" es bastante raro. – Village

Respuesta

21

Puede. hacer la sustitución con una sola llamada a sed:.

sed -i -E 's/([#$%&_\])/\\&/g' file.txt 

el & en el texto de reemplazo rellena para cualquier carácter individual se encierra entre paréntesis Nótese que como \ es el carácter de escape látex, que tendrá que escapar también en el archivo original.

+1

¡Bien hecho! +1 –

+3

Los paréntesis no son necesarios. Algunas versiones de 'sed' no admiten''E', pero usan '-r' en su lugar. Algunas versiones de 'sed' requieren una extensión después de' -i', pero como el OP no proporcionó una en la pregunta, es seguro suponer que no es necesaria. –

+2

Buenos puntos, todos. Iba a mencionar que -E dependería de que la versión esté en uso, pero debe haberla eliminado de la versión final. – chepner

2

Creo que su problema es que bash está manejando esas escapadas.

  1. Lo que me parece correcto. Pero advertencia: también se escapará por partida doble, p. un \# que ya se ha escapado. Si eso no es lo que desea, puede modificar sus patrones para verificar que no haya un precedente \ ya.
  2. $ se usa para la sintaxis de sustitución de comando bash. Supongo que grep "\\$" file.txt debería hacer lo que esperas.
4
sed -i 's/\#/\\\#/g' ./file.txt 
sed -i 's/\$/\\\$/g' ./file.txt 
sed -i 's/\%/\\\%/g' ./file.txt 
sed -i 's/\&/\\\&/g' ./file.txt 
sed -i 's/\_/\\\_/g' ./file.txt 

No es necesario el \ en la primera (búsqueda) cadena en la mayor parte de ellos, sólo $ (es un carácter especial, es decir, el final de una línea, el resto no son especiales) . Y en el reemplazo, solo necesita dos \\, no tres. Además, se puede hacer todo en un solo -e con varias declaraciones:

sed -i.bak -e 's/#/\\#/g' \ 
      -e 's/\$/\\$/g' \ 
      -e 's/%/\\%/g' \ 
      -e 's/&/\\&/g' \ 
      -e 's/_/\\_/g' file.txt 

No es necesario hacer doble escapar nada (excepto el \\) porque estos son entre comillas simples. En su grep, bash está interpretando el escape en el $ porque es un carácter especial (específicamente, un sigilo para variables), por lo que grep está obteniendo y buscando solo el $, que es un carácter especial que significa el final de una línea. Es necesario que sea comilla simple para prevenir bash de interpretar el \ ('\$', o añadir otro par de \\: "\\\$". Presumably, that's where you're getting the \ `de, pero que no lo necesita en el sed como está escrito

+0

Dado que "$" es especial, ¿necesita tres '\' (por ejemplo, '\\\') al frente? – Village

+1

@Village No en el reemplazo. – Kevin

2

no respondo de sed, las otras respuestas son buenos enougth ;-)

Puede utilizar less como visor para comprobar su archivo enorme (o more, pero less es más cómodo que more). Para buscar, puede usar fgrep: ignora la expresión regular =>fgrep '\$' realmente buscará texto \$. fgrep es lo mismo que invocar grep -F.

EDITAR: fgrep '\$' y fgrep "\$" son diferentes. En el segundo caso, bash interpreta la cadena y la reemplazará por un solo carácter: $ (es decir, fgrep buscará solamente $).

Cuestiones relacionadas