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

The$4指的是正则表达式中的第四个捕获括号,在这种情况下:(?=(</?))?. 正如评论所说,这可能是未定义的,因为?最后的意思是“这个东西可能存在,但也可能不存在”。

如果您以某些方式使用未定义的值(通过undefPerl 中的特殊值发出信号),包括在与 的字符串比较中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) :
                                       ""

请注意,在这种特殊情况下,您不必检查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 是 undef,您将收到关于未定义值而不是未初始化值的投诉。

在您执行此 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 回答