0

こんにちは私はシェルスクリプトを使用してXMLのタグ値(値には特殊文字が含まれる場合があります)を設定することに固執しています。

XMLタグの値は二重引用符で囲む必要があります。

要件:タグ値を含むxmlがあります。シェルスクリプトの場合、タグの前に値を含む新しいXMLタグを配置する必要があります。sedを使用しているので、以下のように試しました。$ 4 $ 5に特殊文字がない場合、これは正常に機能します。特殊文字でこれを機能させる方法は?(例:&> <: "。、;'など)

sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" >  <\/CommCellUser> '$test' <jobResulsDir  /' $temp_dir/PreImageModeFile.xml > $temp_dir/PreImageModeFile2.xml

sed以外に他の方法はあります。助けてください

4

3 に答える 3

0

perlを使ってみませんか?シェルスクリプトである必要がありますか?

   #!/usr/bin/perl
   use XML::Simple;
   use Data::Dumper;
   open(my $XML_IN, '<', '/xml/file/path.xml');
   $/=undef;
   my $xml_ref = XMLIn(<$XML_IN>);
   print Dumper \$xml_ref;
   # ... access $xml_ref in appropriate location, adding element / value
   my $new_xml = XMLout($xml_ref);
   close $XML_IN;
   open(my $XML_OUT, '>', '/xml/file/path.xml');
   print $XML_OUT $new_xml;
   close $XML_OUT;
于 2012-11-22T15:34:49.817 に答える
0

sedでやろうとしていることは脳を引き裂きます。それを機能させるには、すべての特殊文字の前にバックスラッシュを使用する必要があります。私はこの種の作業にm4を使用します。例を見る:

define(your_macro_name,<Delete>
<Object fdn="SubNetwork=somemoredata`,SubNetwork=somedata'`,ManagedElement'=$1"/>
</Delete>)dnl

上記のコードを「xmlmacros.m4」という名前のファイルに保存してから、「test.m4」という名前のファイルを作成し、次の内容を追加します。

include(xmlmacros.m4)dnl
your_macro_name(YOURXMLVALUE)

2つのファイルが同じフォルダーにある場合は、実行できm4 test.m4、出力は次のようになります。

 <Delete>
 <Object fdn="SubNetwork=somemoredata,SubNetwork=somedata,ManagedElement=YOURXMLVALUE"/>

ここ$1で、「test.m4」ファイルの括弧内の値に置き換えられます。さらに定義を追加して、xmlヘッダーなどのxmlファイルをオンデマンドで作成することもできます。

上記は、使用できる実用的な例です。あなたはm4の詳細を探すことができます、私はいつもこのタイプの仕事のためにそれを使います。

于 2012-11-22T15:39:42.240 に答える
0

Awkは「特殊文字」を気にしません。これはsedで:

sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" > <\/CommCellUser> '$test' <jobResulsDir /'

これはawkにあります:

awk -v userName="$4" -v password="$5" -v test="$test" '
   /<jobResulsDir/{ sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir ") }
   { print }
'

/<jobResulsDir/ただし、sub()はREが存在する場合にのみ発生するため、実際に事前にテストする必要はありません。そのため、次のように省略できます。

awk -v userName="$4" -v password="$5" -v test="$test" '
   { sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir "); print }
'

これがあなたのコメント/質問が求めていたものであるかどうかはわかりませんが、値の名前を二重引用符で囲む必要がある場合は、スクリプトを微調整して、必要な場所に提供してください。

awk -v userName="$4" -v password="$5" -v test="$test" '
   { sub(/<jobResulsDir/, "<CommCellUser userName=\"" userName "\" password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir "); print }
'

そして最後に、必要に応じて作業を分割して読みやすく効率的にする方法を1つ紹介します。

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   { sub(/<jobResulsDir/, rep); print }
'

そして、そのようにレイアウトされたものを見ると、「特殊文字」を気にしないawkについて少し嘘をついていることがわかります。sub()は実際には1つの「特殊文字」を考慮します。これはsub()で一致したものを逆参照するために使用されるため、置換文字列の「&」であるため、「&」を「\&」に置き換える必要があります。担当者:

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   { gsub(/&/,"\\\\&",rep); sub(/<jobResulsDir/, rep); print }

文字列リテラルはawkで2回解釈されるため(スクリプトが解釈されるときに1回、実行されるときにもう一度)、4 "\" sかかります。したがって、リテラルのバックスラッシュを取得するには、\の代わりに\\が必要です。

必要に応じて、match()とsubstr()を使用する別のアプローチがあり、その制約はありません。

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   match($0,/<jobResulsDir/) {
       $0 = substr($0,1,RSTART) rep substr($0,RSTART+RLENGTH)
   }
   { print }
'

個人的には、エスケープ文字をいじり回すのが嫌いなので、match()/ substr()アプローチを使用します。

そして、私たちが始めたところに戻るために、必要に応じてワンライナーとしてそれを書く方法は次のとおりです。

awk -v userName="$4" -v password="$5" -v test="$test" '{
   print (match($0,/<jobResulsDir/) ? substr($0,1,RSTART) "<CommCellUser userName=\"" userName "\"password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir " substr($0,RSTART+RLENGTH) : $0)
}'
于 2012-11-22T15:45:50.360 に答える