De quais personagens devo escapar ao modificar um arquivo usando sed? [duplicado]

0
    

Esta pergunta já tem uma resposta aqui:

    

Estou usando o seguinte comando sed (com limite de palavras):

sed "7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/" < config.xml

E estou recebendo este erro:

sed: command garbled: 7 s/\<<Filevalue=.*/>\>/<Filevalue="true"/>/

Eu tentei escapar de caracteres especiais, mas ainda recebendo o mesmo erro:

sed "7 s/\<\<Filevalue=.*\/\/\>\>/\<Filevalue=\"true\"\/\>/" < config.xml

O que eu fiz de errado?

EDITAR:

Este é um XML fictício. Valores de Filevalue podem variar.

Conteúdo XML:

<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
    
por Menon 07.05.2015 / 12:25

3 respostas

1

Você também precisa inverter as barras que não funcionam como separadores ou usar um separador diferente:

sed "7 s%\<<Filevalue=.*/>\>%<Filevalue="true"/>%"

Além disso, você não pode incluir aspas duplas entre aspas duplas sem contrashash, ou alternar para aspas simples.

Além disso, uma palavra não pode começar com < , então \<< nunca corresponde.

    
por 07.05.2015 / 12:32
1

O que você fez de errado é tentar analisar XML com uma expressão regular. Esta é uma má ideia - às vezes funciona, mas torna o código frágil. O XML tem uma especificação que permite alimentações de linha, espaço em branco e aninhamento de tags - tudo o que o regex manipula muito mal.

A resposta real é 'use um analisador'.

Sugiro perl e XML::Twig como opções - existem outras:

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => {
        'File' => sub { $_->set_att( 'value', 'true' ) }
    }
);

$twig->parsefile('config.xml');    
$twig->print;

Eu fiz certas suposições sobre o conteúdo do seu XML - se você estiver preparado para dar um exemplo mais extenso, eu vou verificar e garantir que isso funcione como recuado.

Editar:

Com base no snippet que você postou, isso não é um XML válido, portanto, desconsidere o acima. Eu ainda sugiro que você não use algo que se pareça um pouco com XML, chamado output.xml , porque esse é um caminho para todos os tipos de dor e aflição.

Meu código acima funcionará com:

<xml>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/>
   <File value="false"/> 
</xml>

Você pode verificar a validade do XML aqui: link

Se deixarmos de lado o fato de que não é XML - isso funciona:

#!/usr/bin/perl
use strict;
use warnings;

while ( <DATA> ) {
    #amend just line 7
   if ( $. == 7 ) { s,<Filevalue=".*">,<Filevalue="true">,; }
   print;
}
__DATA__
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">

Qual você pode escolher por:

perl -nle 'if ( $.==7) {s,<Filevalue=".*">,<Filevalue="true">,g;} print;' notxml.txt
    
por 07.05.2015 / 12:40
0
Choroba está mais certo ... mas ele está enganando sobre as aspas duplas: isso não é um problema para o sed, mas é para o shell.

Você só precisa escapar de * [ ] \ . e do delimitador (por padrão, / ). No seu caso, acredito que isso funcionaria melhor:

sed '7s%<<\([^>]*\)>>%<>%' file

Se funcionar, use a opção -i para substituí-lo no arquivo.

Explicação:

  • O \( \) agrupa uma expressão e é substituído no lado direito por \
  • O [^>]* engloba todos os caracteres até o próximo colchete de ângulo reto.
  • Assim, qualquer coisa entre os colchetes incorretos será substituída pela mesma expressão em um. Observe que isso acontecerá somente uma vez na linha 7, a menos que você anexe o sinalizador g ao comando s .
por 07.05.2015 / 14:05