J'ai beaucoup de fichiers XML, plus de 50000 d'entre eux.
Dans certains fichiers XML, certains fichiers sont écrits comme ceci
<filename>abc.JPEG<^Lilename>
^L
est juste un caractère, mais je ne trouve pas ce que ^L
signifie Google.
Lorsque j'utilise cat
pour imprimer le contenu d'un fichier, il s'affiche comme suit
<filename>abc.JPEG<
ilename>
Quoi qu'il en soit, je veux passer <filename>abc.JPEG<^Lilename>
à<filename>abc.JPEG</filename>
J'ai déjà trouvé une commande pour changer un mot dans de nombreux fichiers, tels que
find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;
Mais cette commande ne fonctionne pas dans mon cas, car elle ne peut pas reconnaître le mot recherché lorsque je tape juste ^L
.
Comment puis - je changer <filename>abc.JPEG<^Lilename>
pour <filename>abc.JPEG</filename>
de nombreux fichiers?
<\filename>
plutôt que</filename>
dans un contexte où\f
serait interprété comme le caractère de flux de formulaire. Vous devriez probablement retrouver la source de ces fichiers et signaler le problème avec leur outil de génération au développeur. Pour réparer les fichiers, la réponse acceptée est très bien.Réponses:
Control-L (représenté par
^L
) est le caractère "saut de page". En ASCII, il a la valeur décimale 12 (L
est la 12e lettre de l'alphabet) ou la valeur hexadécimale 0c:Vous pouvez le remplacer à l'aide d'outils comme sed en spécifiant le code d'échappement hexadécimal:
Alternativement, composez
^L
directement en utilisant la séquence de clavier CTRL+ V CTRL+LPour votre remplacement spécifique, étant donné
puis
(le
g
modificateur est ajouté dans le cas où il y a plus d'une instance par ligne).la source
find
qui faisait une boucle sur ces 50000 fichiers XML et les traitait automatiquement (et faisait également une sauvegarde).Comme le souligne Hans-Martin Mosner dans les commentaires, il semble que quelqu'un ait utilisé des barres obliques inverses au lieu de barres obliques lors de la génération du XML (ou peut-être exécuté toute la
<filename>
section via un convertisseur Unix-vers-Windows qui était trop zélé pour les barres obliques).\f
est une séquence d'échappement rarement utilisée pour un caractère de saut de page, alias U + 0C ou ^ L. Ainsi, une étape ultérieure du pipeline a ensuite remplacé le\f
par des caractères littéraux U + 0C.Heureusement, U + 0C est un caractère extrêmement rare qui ne sera probablement pas trouvé intentionnellement dans n'importe quel type de XML. Et puisque seulement
\f
produirait ce, par opposition à ( par exemple)\g
ou\k
, une découverte et remplacement universel devrait fixer non seulement ,</filename>
mais aussi</folder>
,</file>
ou toute autre chose qui a obtenu estropié.C'est ce que fait le script sed de steeldriver; Je ferais juste un peu plus général:
Cela signifie "(s) wap toutes les instances de
\x0c
(c'est-à-dire, U + 0C) à/f
, (g) lobalement".la source
\f
est le caractère de flux de formulaire en Perl. Il semble que ces fichiers mal formés aient été créés par quelqu'un de nouveau à Perl et XML.Voici un correctif beaucoup plus Perlier - qui répond également aux objectifs du PO d'automatiser la mise à jour de tous les fichiers, contrairement à la réponse acceptée avec sed, qui ne fonctionnera que sur un fichier à la fois car il n'est pas associé
find
.\f
peut simplement être utilisé lui-même au lieu du code hexadécimalx0c
.Ici, j'ai ajouté
-type f
à telfind
pour ne renvoyer que des fichiers simples - sinon,find
il reviendra.
dans la liste et déclenchera un avertissement lorsque vous essayez de le modifier, bien que tout le reste fonctionne.J'ai également rendu l'expression plus facile à voir en utilisant le
x
drapeau qui ignore les espaces blancs réels, vous permettant d'espacer les éléments de votre expression régulière. Si vous n'aimez pas ça, le voici sans:Et dans le cas probable où tous les caractères de flux de formulaire sont faux et tous devraient être remplacés par
/f
, alors vous pouvez affiner encore plus le one-liner:Vous n'avez pas besoin d'utiliser des barres obliques pour entourer les éléments de votre commande de substitution de regex (
s///
) en Perl. Vous pouvez utiliser n'importe quel symbole. Si vous choisissez d'utiliser n'importe quel type de symbole en forme de parenthèse, cependant, vous devez utiliser les deux:s[old][new]
par exemple.Comme je n'utilise pas de barres obliques, je n'ai pas à échapper à aucune barre oblique.
Quant à
-i.bkp
:perl -pi -e
vous permet de modifier sur place - mais si vous voulez une assurance supplémentaire au cas où vous auriez mal votre programme de recherche et remplacement Perl, vous pouvez mettre une extension de fichier afin qu'il fasse une copie des fichiers originaux pour vous. Ici, je l'ai utilisé.bkp
.Dans les versions les plus récentes de Perl, l'édition sur place a été mise à jour pour être plus résistante au cas où votre système souffrirait également d'un problème grave comme une panne de courant ou un manque d'espace disque. Voici l'auteur de Perl, Brian D Foy, sur l'amélioration de l'édition in situ dans les Perls récents.
Vous devriez envisager d'utiliser Perl pour ce type de tâches, car il s'agit d'un langage de programmation à usage général extrêmement puissant mais sous-évalué, dont l'un des objectifs de conception d'origine était de remplacer
sed
etawk
avec quelque chose de bien meilleur.Les capacités de correspondance regex de Perl 5 et la syntaxe regex améliorée dépassent de loin celles de
sed
,awk
et en fait tous les autres langages de programmation à part Perl 6, faisant de Perl le choix le plus judicieux pour les manipulations regex simples et avancées.Pour clarifier:
sed
fonctionnera bienfind
aussi et vous pouvez également utilisersed -i.bkp
pour faire une sauvegarde de chaque fichier modifié, mais pour autant que je sache, il ne dispose pas de la résilience supplémentaire dans Perl 5.28 et supérieur. Il utilise également la syntaxe regex UNIX ® traditionnelle plus maladroite et beaucoup moins puissante.la source