sedを使用してファイルを変更するときは、どの文字をエスケープする必要がありますか? [コピー]

sedを使用してファイルを変更するときは、どの文字をエスケープする必要がありますか? [コピー]

次のsedコマンドを使用しています(単語の境界を含む)。

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

次のエラーが発生します。

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

特殊文字をエスケープしようとしましたが、まだ同じエラーが発生します。

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

私は何が間違っていましたか?

編集する:

これはダミーXMLです。ファイル値の値は異なる場合があります。

XMLコンテンツ:

<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">
<Filevalue="false">

答え1

また、区切り文字として使用できないスラッシュはバックスラッシュとして扱うか、別の区切り文字を使用する必要があります。

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

また、バックスラッシュを使用せずに二重引用符内に二重引用符を含めたり、二重引用符に切り替えることはできません。

また、単語はで始めることができないため、<絶対\<<一致しません。

答え2

あなたが間違っているのは、正規表現を使用してXMLを解析しようとしていることです。これは悪い考えです。時には動作しますが、壊れやすいコードを生成します。 XML には、改行、スペース、およびネストしたタグを受け入れる仕様があります。これらの項目はすべて正規表現では非常に正しく処理されません。

実際の答えは「パーサーを使用してください」です。

私はオプションとしてとをperlお勧めしますが、他のオプションもあります。XML::Twig

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;

私はXMLの内容について特定の仮定をしています。より広範な例を提供する準備ができている場合は、インデントが機能するように機能していることを再確認します。

編集する:

あなたが投稿したコードスニペットによると、これは有効なXMLではないので、上記を無視してください。それにもかかわらず、いわゆるXMLと似ているものを使用しないことをお勧めします。output.xmlこれは、あらゆる種類の苦痛と不幸をもたらす経路であるためです。

上記のコードは次のように動作します。

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

ここでXMLの妥当性を確認できます。http://www.xmlvalidation.com/index.php?id=1&L=0

XMLではないという事実を除いて、次のように動作します。

#!/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">

次のいずれかの方法でこれを実行できます。

perl -nle 'if ( $.==7) {s,<Filevalue=".*">,<Filevalue="true">,g;} print;' notxml.txt

答え3

chorobは基本的に正しいです。しかし、彼は二重引用符について誤解を招く。 sedには問題ではありませんが、シェルには問題があります。

エスケープと区切り文字のみが必要です* [ ] \ .(デフォルトでは/)。あなたの場合は、これが最も効果的だと思います。

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

有効な場合は、この-iオプションを使用してファイルを置き換えます。

説明する:

  • 式セットは\( \)右から次に置き換えられます。\
  • [^>]*次の右山かっこまですべての文字を飲み込みます。
  • したがって、誤った二重括弧内の内容は、二重括弧内の同じ式に置き換えられます。これはただ起こります。一度コマンドgにフラグを追加しない限り、7行目にあります。s

関連情報