Tengo muchos archivos XML, más de 50000 de ellos.
En algunos archivos XML, algunos archivos se escriben así
<filename>abc.JPEG<^Lilename>
^L
es solo un personaje, pero no puedo encontrar lo que ^L
significa con Google.
Cuando uso cat
para imprimir el contenido de un archivo, se muestra como el siguiente
<filename>abc.JPEG<
ilename>
De todos modos, quiero cambiar <filename>abc.JPEG<^Lilename>
a<filename>abc.JPEG</filename>
Ya encontré algún comando para cambiar una palabra en muchos archivos, como
find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;
Pero ese comando no funciona en mi caso, porque no puede reconocer la palabra de búsqueda cuando escribo ^L
.
¿Cómo puedo cambiar <filename>abc.JPEG<^Lilename>
a <filename>abc.JPEG</filename>
muchos archivos?
<\filename>
lugar de</filename>
en un contexto en el\f
que se interpretaría como el personaje del formulario. Probablemente deberías rastrear la fuente de estos archivos y señalar el problema con su herramienta de generación al desarrollador. Para arreglar los archivos, la respuesta aceptada está bien.Respuestas:
Control-L (representado como
^L
) es el carácter de "avance de formulario". En ASCII, tiene un valor decimal 12 (L
es la 12ª letra del alfabeto) o un valor hexadecimal 0c:Puede reemplazarlo utilizando herramientas como sed especificando el código de escape hexadecimal:
Alternativamente, componga
^L
directamente usando la secuencia del teclado CTRL+ V CTRL+LPara su reemplazo específico, dado
entonces
(el
g
modificador se agrega en caso de que haya más de una instancia por línea).fuente
find
mensaje que recorriera esos 50000 archivos XML y procesara automáticamente cada uno (y también hiciera una copia de seguridad).Como Hans-Martin Mosner señala en los comentarios, parece que alguien usó barras diagonales inversas en lugar de barras diagonales hacia adelante al generar el XML (o posiblemente ejecutó toda la
<filename>
sección a través de un convertidor de Unix a Windows que estaba demasiado celoso de las barras).\f
es una secuencia de escape raramente utilizada para un personaje de alimentación de formulario, también conocido como U + 0C o ^ L. Entonces, algún paso posterior de la tubería luego reemplazó los caracteres\f
literales U + 0C.Afortunadamente, U + 0C es un personaje extremadamente raro que es poco probable que se encuentre intencionalmente en ningún tipo de XML. Y ya que sólo
\f
produciría esto, en lugar de (por ejemplo)\g
o\k
, un hallazgo y reemplazo universal, debe fijar no sólo</filename>
, sino también</folder>
,</file>
o cualquier otra cosa que quedó destrozado.Eso es lo que hace el script sed de steeldriver; Simplemente lo haría un poco más general:
Esto significa "(s) wap todas las instancias de
\x0c
(es decir, U + 0C) a/f
, (g) lobally".fuente
\f
es el carácter de alimentación de formulario en Perl. Parece que estos archivos con formato incorrecto fueron creados por alguien nuevo en Perl y XML.Aquí hay una solución mucho más Perlier, que también cumple con los objetivos del OP de automatizar la actualización de todos los archivos, a diferencia de la respuesta aceptada con sed, que solo funcionará en un archivo a la vez, ya que no está emparejado
find
.\f
simplemente puede emplearse en lugar del código hexadecimalx0c
.Aquí agregué
-type f
a telfind
para que solo devuelva archivos sin formato; de lo contrariofind
, volverá a aparecer.
en la lista y activará una advertencia cuando intente editarlo, aunque todo lo demás seguirá funcionando.También hice que la expresión regular sea más fácil de ver usando la
x
bandera que ignora el espacio en blanco real, lo que le permite espaciar los elementos de su expresión regular. Si no te gusta esto, aquí está sin:Y en el caso probable de que todos los caracteres de alimentación de formularios sean espurios y todos deben ser reemplazados por
/f
, entonces puede reducir aún más la línea:No necesita utilizar barras diagonales para rodear los elementos de su comando de sustitución de expresiones regulares (
s///
) en Perl. Puedes usar cualquier símbolo. Sin embargo, si elige usar cualquier tipo de símbolo pareado entre paréntesis, debe usar ambos:s[old][new]
por ejemplo.Como no estoy usando barras, no tengo que escapar de ninguna barra.
En cuanto a
-i.bkp
: leperl -pi -e
permite editar en el lugar, pero si desea un seguro adicional en caso de que su programa Perl de buscar y reemplazar sea incorrecto, puede colocar una extensión de archivo para que haga una copia de los archivos originales para tú. Aquí lo he usado.bkp
.En las versiones más recientes de Perl, la edición en el lugar se ha actualizado para que sea más resistente en caso de que su sistema sufra un problema grave como pérdida de energía o quedarse sin espacio en disco. Aquí está el autor de Perl, brian d foy, sobre la edición in situ mejorada en Perls recientes.
Debería considerar usar Perl para este tipo de tareas, porque es un lenguaje de programación de propósito general extremadamente potente pero subestimado, uno de cuyos objetivos de diseño originales era reemplazar
sed
yawk
con algo mucho mejor.Las capacidades de coincidencia de expresiones regulares de Perl 5 y la sintaxis de expresiones regulares mejoradas superan con creces las de
sed
,awk
y de hecho cualquier otro lenguaje de programación, aparte de Perl 6, lo que hace que Perl sea la opción más sensata para manipulaciones de expresiones regulares simples y avanzadas.Para aclarar:
sed
también funcionará bienfind
y también puede usarsed -i.bkp
para hacer una copia de seguridad de cada archivo editado, pero que yo sepa, no presenta la resistencia adicional en Perl 5.28 y superior. También utiliza la sintaxis tradicional de expresiones regulares de UNIX ® más clunkier y mucho menos potente.fuente