Bashを使用したxmlファイルの追加

Bashを使用したxmlファイルの追加

フォーラムの良い人がこのスクリプトを作成するのを手伝ってくれましたが、私が投げたものはすべてエラーを出力し、なぜ問題が何であるのかわかりません。 bash test.shをリクエストすると、Ubuntu端末ですべてのスクリプトを実行しました。

私の目標は、複数の.xmlファイルにタグを追加することですが、process></process>一部のファイルには1〜100個のタグがあります。

例:

 - jfksaJDFH
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - jdhkjasdh
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>
 - <process>value=""</process>

スクリプト以降:

 - jfksaJDFH
 - <process>value="1"</process>
 - <process>value="2"</process>
 - <process>value="3"</process>
 - <process>value="4"</process>
 - jdhkjasdh
 - <process>value="5"</process>
 - <process>value="6"</process>
 - <process>value="7"</process>
 - <process>value="8"</process>

スクリプト:

#!/bin/bash

dir="/mnt/Desktop/test/"

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "<process>value=\"$((i++))\"</process>"
        else
           echo "$line"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

上記のスクリプトが実行されたら、最後のスクリプトを削除します。<process>value=""</process>

スクリプトを次のように変更します。

while IFS= read -r -d '' file
do
    i=1
    while IFS= read -r -u 3 line
    do
        if [[ $line = '<process></process>' ]]; then
           echo "$line"
        else
           echo "<process>value=\"$((i++))\"</process>"
        fi
    done 3< "$file" > "$file.xml"
done < <(find $dir -type f -name \*.xml -print0)

ファイルの出力は次のとおりです。

<process>value="1"</process>
<process>value="2"</process>
<process>value="3"</process>
<process>value="4"</process>
<process>value="5"</process>
<process>value="6"</process>
<process>value="7"</process>
<process>value="8"</process>
<process>value="9"</process>
<process>value="10"</process>
<process>value="11"</process>
<process>value="12"</process>
<process>value="13"</process>
<process>value="14"</process>
<process>value="15"</process>
<process>value="16"</process>
<process>value="17"</process>
<process>value="18"</process>
<process>value="19"</process>
<process>value="20"</process>
<process>value="21"</process>
<process>value="22"</process>
<process>value="23"</process>

つまり、これはページ内の他のすべてのエントリを追加しますが削除します。

答え1

このスクリプトをファイルに入れます(例: 'increase.awk'):

BEGIN { i = 1 }
/.*<process>value=""<\/process>.*/ { split($0, a, "value=\"\"") ; print a[1] "value=\"" i++ "\"" a[2] ; next }
/.*/ { print $0 }

それから電話してください。

gawk -f increase.awk < yourinputfile

説明:awkでは、split("string", a, "separatorstring")「separatorstring」を区切り文字として使用して、「string」をaという配列に分割します。したがって、a[1]には最初の「区切り文字列」までのすべての内容が含まれ、a[2]には行末または次の「区切り文字列」までのすべての内容が含まれます。

答え2

このXMLを使用しないでください。必要に応じて考えてみてください。 XMLは、スペースを積極的に無視する構造化データ型です。 eg<attr name="fish" />などの単項タグがあるということは、正規表現を使って1行ずつ解析すると、いつかコードが奇妙にクラッシュすることを意味します。

これを行う方法は、XMLパーサーを使用することです。どちらを使うかは個人的な好みの問題ですが、私はスクリプトXML::Twig(perlモジュール)が好きです。

説明したように問題を解決するには:

#!/usr/bin/env perl

use strict;
use warnings;

use XML::Twig;

sub increment_value {
    my ( $twig, $process ) = @_;
    my ($value) = ( $process->text =~ m/(\d+)/ );
    print "Got $value\n";
    if ( defined ( $value ) ) { 
        $process->set_text( 'value="' . ++$value . '"' );
    } 
    else {
        $process -> delete;
    }
}

my $twig = XML::Twig->new(
    'pretty_print'  => 'indented',
    'twig_handlers' => { 'process' => \&increment_value },
);
$twig->parsefile( 'your_file.xml'  );
$twig->print;    #prints to stdout.

processこれは、テキストを抽出、変換、および置換する要素ごとの「処理」をトリガーします。

答え3

スクリプトを再構築する際に、if-then-else構文のロジックが復元されたことをご存知でしたか?

以下のコメント行1と2の位置を確認してください。書き直されたコードでこれを逆にしました。

そしてIFS =は-r -d ''ファイルを読み込みます。
する
    私=1
    そしてIFS = read -r -u 3行
    する
        if [[$line = '']];
           echo "value=\"$((i++))\"" # 行 1******************
        その他
           echo "$line" # 2行目********************
        フィリピン諸島
    3つの「$ file.xml」を完了してください。
完璧

関連情報