2012-08-24 85 views
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。有人可以幫我嗎?

+0

你必須讓你的行號關閉,錯誤似乎來自行'($ 1和($ 4 eq「 ardnew

+0

我正在使用'Perl-5.10.1' – cybertextron

+0

Obligatory:http ://stackoverflow.com/a/1732454/9719 – darch

回答

4

$4指正則表達式中的第四個捕獲括號,在這種情況下爲:(?=(</?))?。正如評論所述,這可能是不確定的,因爲?最終意味着「這件事可能在那裏,但它也可能不是」。

如果您以某種方式使用未定義的值(通過Perl中的特殊值undef發出信號),包括與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),但它也不會傷害。

+0

幾乎那裏...現在它不喜歡'<(/?)([^/>] +)(/?) >' – cybertextron

+0

下載一個XML漂亮打印機窗體CPAN。不用解析器的好處,就可以節省您試圖解析XML的痛苦。 –

+0

@LenJaffe你能給我更多的細節嗎? – cybertextron

-2

如果它工作正常,那麼你可以忽略警告。這條線

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

更改爲

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

但它會更好/更好用一些XML解析器庫來解析XML ...

問候,

+0

我已經嘗試了這麼多,但所有的失敗,由於一些隨機問題。 – cybertextron

0

除非有沒有存在的最後一場比賽:

(?=(</?))? 

如果最終問號允許比賽繼續進行置換,然後$4undef。例如(使用Perl 5.10或更高,老年人就應該是安全的使用||代替//):

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

你只需要警惕的是或關閉警告。您不能將捕獲移動到零寬度前面,因爲它總是將$4設置爲空字符串。

0

所以這個運行時錯誤告訴你,鑑於你當前的輸入,$ 4沒有價值,但是你仍然在訪問它。

所以行:

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

在撒謊。如果$ 4是undef,那麼您會收到一個關於未定義值的投訴,而不是未初始化的值。

$ 4在執行此s {} {}語句時不匹配任何內容。

除非你必須寫一個XML漂亮的打印機,你應該從CPAN得到一個。