1
@files = glob "*.xml";

undef $/;
for $file (@files) {
    $indent = 0;
    open FILE, $file or die "Couldn't open $file for reading: $!";
    $_ = readline *FILE;
    close FILE or die "Couldn't close $file: $!";

    # Remove whitespace between > and < if that is the only thing separating them
    s/(?<=>)\s+(?=<)//g;

    # Indent
    s{  # Capture a tag <$1$2$3>,
        # a potential closing slash $1
        # the contents $2
        # a potential closing slash $3
        <(/?)([^/>]+)(/?)> 

        # Optional white space
        \s*

        # Optional tag.
        # $4 contains either undef, "<" or "</"
        (?=(</?))?
    }
    {
        # Adjust the indentation level.
        # $3: A <foo/> tag. No alteration to indentation.
        # $1: A closing </foo> tag. Drop one indentation level
        # else: An opening <foo> tag. Increase one indentation level
        $indent +=
            $3 ?  0 :
            $1 ? -1 :
                  1;

        # Put the captured tag back into place
        "<$1$2$3>" .
        # Two closing tags in a row. Add a newline and indent the next line
        ($1 and ($4 eq "</") ?
            "\n" . ("  " x $indent) : 
        # This isn't a closing tag but the next tag is. Add a newline and
        # indent the next line.
        $4 ?
            "\n" . ("  " x $indent) :
        # This isn't a closing tag - no special indentation. I forget why
        # this works.
            ""
        )
    # /g repeat as necessary
    # /e Execute the block of perl code to create replacement text
    # /x Allow whitespace and comments in the regex
    }gex;

    open FILE, ">", $file or die "Couldn't open $file for writing: $!";
    print FILE or die "Couldn't write to $file: $!";
    close FILE or die "Couldn't close $file: $!";
}

このコードを使用して、一連のxmlファイルを正しくインデントしています。ただし、実行すると次のようになります。

Use of uninitialized value $4 in string eq at C:/Users/souzamor/workspace/Parser/xmlreformat.pl line 25.

line 25は:

# $4 contains either undef, "<" or "</"

なぜなのかわかりませんが、初めてですPerl。誰か助けてくれませんか?

4

4 に答える 4

4

$4、正規表現の4番目のキャプチャ括弧を指します。この場合は次のようになります(?=(</?))??コメントが述べているように、これは「これはそこにあるかもしれないが、そうではないかもしれない」という意味の最後にあるため、定義されていない可能性があります。

undefとの文字列比較など、特定の方法で未定義の値(Perlの特別な値を介して通知される)を使用するとeq、Perlから警告が表示されます。変数がで定義されているかどうかを簡単に確認できますdefined($var)

あなたの特定のケース$4では、このフレーズで使用されています:

($1 and ($4 eq "</") ? "\n" . ("  " x $indent) : 
 $4                  ? "\n" . ("  " x $indent) :
                       ""

警告の修正は、これらのテストを次のように置き換えるのと同じくらい簡単です。

($1 and defined($4) and ($4 eq "</") ? "\n" . ("  " x $indent) : 
$4                                   ? "\n" . ("  " x $indent) :
                                       ""

この特定のケースでは、2行目でチェックする必要はありませんがdefined($4)、どちらも害はないことに注意してください。

于 2012-08-24T16:28:37.233 に答える
0

そこに最終的な一致がない場合を除いて:

(?=(</?))?

その最後の疑問符で一致が置換に進むことができる場合は、に$4なりますundef。たとえば(Perl 5.10以降を使用している場合、古い場合は||代わりに安全に使用できます//):

(($4 // '') eq "</")

それを防ぐか、警告をオフにする必要があります。$4キャプチャは常に空の文字列に設定されるため、ゼロ幅の先読みの外に移動することはできません。

于 2012-08-24T16:34:00.157 に答える
0

したがって、この実行時エラーは、現在の入力を考えると、$ 4には価値がないことを示していますが、とにかくそれにアクセスしています。

したがって、行:

 # Optional tag.
 # $4 contains either undef, "<" or "</"

嘘をついている。$ 4が未定義の場合、初期化されていない値ではなく、未定義の値について苦情が寄せられます。

このs{}{}ステートメントを実行した時点では、$4は何にも一致していません。

XMLプリティプリンターを作成する必要がない限り、CPANから入手する必要があります。

于 2012-08-24T16:43:16.750 に答える
-2

正しく機能している場合は、警告を無視できます。この行を変更します

close FILE or die "Couldn't close $file: $!";

 close FILE or die "Couldn't close $file: $!";
 no warnings 'uninitalized';

しかし、xmlを解析するためにいくつかのxmlパーサーライブラリを使用する方が良い/より良いでしょう...

よろしく、

于 2012-08-24T16:26:17.063 に答える