Eu tenho muitos arquivos XML, mais de 50000 deles.
Em alguns arquivos XML, alguns arquivos são gravados assim
<filename>abc.JPEG<^Lilename>
^L
é apenas um caractere, mas não consigo encontrar o que ^L
significa com o Google.
Quando eu uso cat
para imprimir o conteúdo de um arquivo, ele aparece como o seguinte
<filename>abc.JPEG<
ilename>
De qualquer forma, quero mudar <filename>abc.JPEG<^Lilename>
para<filename>abc.JPEG</filename>
Eu já encontrei algum comando para alterar uma palavra em muitos arquivos, como
find . -exec perl -pi -e 's/[find_word]/[change_word]/g' {} \;
Mas esse comando não funciona no meu caso, porque não pode reconhecer a palavra de pesquisa quando eu apenas digito ^L
.
Como posso mudar <filename>abc.JPEG<^Lilename>
para <filename>abc.JPEG</filename>
em muitos arquivos?
<\filename>
vez de</filename>
em um contexto em\f
que seria interpretado como o caractere de feed de formulário. Você provavelmente deve rastrear a origem desses arquivos e apontar o problema com a ferramenta de geração para o desenvolvedor. Para corrigir os arquivos, a resposta aceita é ótima.Respostas:
Control-L (representado como
^L
) é o caractere "feed de formulário". No ASCII, ele possui o valor decimal 12 (L
é a 12ª letra do alfabeto) ou o valor hexadecimal 0c:Você pode substituí-lo usando ferramentas como sed especificando o código de escape hexadecimal:
Como alternativa, componha
^L
diretamente usando a sequência do teclado CTRL+ V CTRL+LPara sua substituição específica, dado
então
(o
g
modificador é adicionado caso haja mais de uma instância por linha).fonte
find
loop sobre esses 50000 arquivos XML e processasse automaticamente cada um (e fizesse um backup também).Como Hans-Martin Mosner aponta nos comentários, parece que alguém usou barras invertidas em vez de barras ao gerar o XML (ou possivelmente executou toda a
<filename>
seção através de um conversor Unix para Windows que era muito zeloso em relação a barras).\f
é uma sequência de escape raramente usada para um caractere de avanço de formulário, também conhecido como U + 0C ou ^ L. Portanto, alguma etapa posterior do pipeline substituiu os\f
caracteres U + 0C literais.Felizmente, U + 0C é um caractere extremamente raro que dificilmente será encontrado intencionalmente em qualquer tipo de XML. E uma vez que apenas
\f
produziria isso, em oposição a (digamos)\g
ou\k
, uma busca e substituição universal deve corrigir não apenas,</filename>
mas também</folder>
,</file>
ou qualquer outra coisa que ficou mutilado.É isso que o sed-script da steeldriver faz; Eu apenas tornaria isso um pouco mais geral:
Isso significa que "(s) trocamos todas as instâncias de
\x0c
(isto é, U + 0C) para/f
, (g) globalmente".fonte
\f
é o caractere de feed de formulário no Perl. Parece que esses arquivos malformados foram criados por alguém novo no Perl e no XML.Aqui está uma correção muito Perlier - que também atende aos objetivos do OP de automatizar a atualização de todos os arquivos, ao contrário da resposta aceita com sed, que só funcionará em um arquivo por vez, pois não está emparelhado com
find
.\f
pode simplesmente ser empregado em vez do código hexadecimalx0c
.Aqui eu adicionei
-type f
ao telfind
para retornar apenas arquivos simples - caso contráriofind
, retornará.
à lista e acionará um aviso quando você tentar editá-lo, embora tudo o mais ainda funcione.Também facilitei a visualização do regex usando a
x
flag que ignora o espaço em branco real, permitindo espaçar os elementos do seu regex. Se você não gosta disso, aqui está sem:E, no provável caso de todos os caracteres de feed de formulário serem falsos e todos serem substituídos por
/f
, você pode reduzir ainda mais a linha única:Você não precisa usar barras para cercar os elementos do comando de substituição de expressões regulares (
s///
) no Perl. Você pode usar qualquer símbolo. Se você optar por usar qualquer tipo de símbolo parecido com colchete, no entanto, precisará usar os dois:s[old][new]
por exemplo.Como não estou usando barras, não preciso escapar de nenhuma barra.
Quanto a
-i.bkp
:perl -pi -e
permite editar no local - mas se você quiser um seguro extra, caso o programa Perl encontre e substitua errado, você pode colocar uma extensão de arquivo para que ele faça uma cópia dos arquivos originais para você. Aqui, eu usei.bkp
.Nas versões mais recentes do Perl, a edição no local foi atualizada para ser mais resiliente, caso o seu sistema sofra um problema sério, como perda de energia ou falta de espaço em disco também. Aqui está o autor do Perl, Brian Doye, sobre a edição aprimorada no local nos Perls recentes.
Você deve considerar o uso de Perl para esses tipos de tarefas, porque é uma linguagem de programação de uso geral extremamente poderosa, porém subestimada, cujo objetivo original do projeto era substituir
sed
eawk
por algo muito melhor.Os recursos de correspondência de regex do Perl 5 e a sintaxe aprimorada de regex excedem em muito os de
sed
,awk
e de fato qualquer outra linguagem de programação além do Perl 6, tornando o Perl a escolha mais sensata para manipulações simples e avançadas de regex.Para esclarecer:
sed
também funcionará bemfind
e você também podesed -i.bkp
fazer um backup de cada arquivo editado, mas até onde eu sei, ele não apresenta a resiliência extra no Perl 5.28 e posterior. Ele também usa a sintaxe de regex UNIX® tradicional, muito mais barulhenta e menos poderosa.fonte