Como posso adicionar quebras de linha em um arquivo XML da linha de comando do Unix?

5

Eu tenho um arquivo XML grande. Na linha de comando do Unix, gostaria de adicionar uma nova linha após cada > .

Eu tentei usar sed para isso, sem sorte:

sed -i '' -e's/>/>\n/' file.xml

Isso apenas insere a letra n , não uma nova linha. Eu também tentei \r e \r\n .

Como posso fazer isso?

(FYI - estou usando o zshell no OSX.)

    
por Nathan Long 16.09.2011 / 16:41

3 respostas

15

Script

Use indentxml file.xml para ver, indentxml file.xml > new.xml para editar.

Onde indentxml é

#!/usr/bin/perl
#
# Purpose: Read an XML file and indent it for ease of reading
# Author:  RedGrittyBrick 2011. 
# Licence: Creative Commons Attribution-ShareAlike 3.0 Unported License
#
use strict;
use warnings;

my $filename = $ARGV[0];
die "Usage: $0 filename\n" unless $filename;

open my $fh , '<', $filename
  or die "Can't read '$filename' because $!\n";
my $xml = '';
while (<$fh>) { $xml .= $_; }
close $fh;

$xml =~ s|>[\n\s]+<|><|gs;                       # remove superfluous whitespace
$xml =~ s|><|>\n<|gs;                            # split line at consecutive tags

my $indent = 0;
for my $line (split /\n/, $xml) {

  if ($line =~ m|^</|) { $indent--; }

  print '  'x$indent, $line, "\n";

  if ($line =~ m|^<[^/\?]|) { $indent++; }             # indent after <foo
  if ($line =~ m|^<[^/][^>]*>[^<]*</|) { $indent--; }  # but not <foo>..</foo>
  if ($line =~ m|^<[^/][^>]*/>|) { $indent--; }        # and not <foo/>

}

Analisador

Naturalmente, a resposta canônica é usar um analisador XML adequado.

# cat line.xml
<a><b>Bee</b><c>Sea</c><d><e>Eeeh!</e></d></a>

# perl -MXML::LibXML -e 'print XML::LibXML->new->parse_file("line.xml")->toString(1)'
<?xml version="1.0"?>
<a>
  <b>Bee</b>
  <c>Sea</c>
  <d>
    <e>Eeeh!</e>
  </d>
</a>

Utilitário

Mas talvez o mais fácil seja

# xmllint --format line.xml
<?xml version="1.0"?>
<a>
  <b>Bee</b>
  <c>Sea</c>
  <d>
    <e>Eeeh!</e>
  </d>
</a>
    
por 16.09.2011 / 17:06
2

Não há sequência de escape, você precisa literalmente usar o caractere de nova linha. Então, para esta entrada

$ cat /tmp/example 
<this is one tag><this is another tag><here again>

Você teria que usar

$ sed -e 's_>_&\
_g' /tmp/example

que produz

<this is one tag>
<this is another tag>
<here again>

Note que a nova linha tem que ser escapada (como mostrado acima)

    
por 16.09.2011 / 17:35
0

Seu comando funciona corretamente, mas não o suficiente.

Tente adicionar a opção 'g' ao final do comando 's'ubstitute para fazer o sed examinar TODOS os' > ' caracteres em cada linha do arquivo de entrada.

Uso:

sed -i -e 's/>/>\n/g' file.xml

anote o "g" no comando substituto.

a parte sufixo da opção '-i' é opcional e pode ser omitida.

As outras respostas dadas funcionam bem também, mas sua tentativa inicial estava correta, embora faltasse a opção 'g'lobal.

    
por 17.09.2011 / 08:56