2016-03-22 4 views
1

Es gibt bereits mehrere good discussions von regular expressions and empty lines auf SO. Ich werde diese Frage entfernen, wenn es sich um ein Duplikat handelt.Unterschiede zwischen leeren und leeren Zeilen in Regexps

Kann jemand erklären, warum dieses Skript 5 3 4 5 4 3 anstelle von 4 3 4 4 4 3 ausgibt? Wenn ich es im Debugger $blank und $classyblank starte bleibe bei "4" (was ich vermute, ist der richtige Wert) bis kurz vor der print-Anweisung.

my ($blank, $nonblank, $non_nonblank, 
    $classyblank, $classyspace, $blanketyblank) = 0 ; 

while (<DATA>) { 

    $blank++ if /\p{IsBlank}/   ; # POSIXly blank - 4? 
    $nonblank++ if /^\P{IsBlank}$/ ; # POSIXly non-blank - 3 
    $non_nonblank++ if not /\S/  ; # perlishly not non-blank - 4 
    $classyblank++ if /[[:blank:]]/ ; # older(?) charclass blankness - 4? 
    $classyspace++ if /^[[:space:]]$/ ; # older(?) charclass whitespace - 4 
    $blanketyblank++ if /^$/   ; # perlishly *really empty* - 3 

} 

print join " ", $blank, $nonblank, $non_nonblank, 
      $classyblank, $classyspace, $blanketyblank , "\n" ; 

__DATA__ 

line above only has a linefeed this one is not blank because: words 

this line is followed by a line with white space (you may need to add it) 

then another blank line following this one 

THE END :-\ 

Ist es etwas mit dem __DATA__ Abschnitt zu tun oder bin ich Missverständnis reguläre Ausdrücke POSIX?


ps:

Wie auf einer fristgerechten Beitrag in Kommentar bemerkt elsewhere "wirklich leer" (/^$/) können Nicht-Leere verpassen:

perl -E 'my $string = "\n" . "foo\n\n" ; say "empty" if $string =~ /^$/ ;' 
perl -E 'my $string = "\n" . "bar\n\n" ; say "empty" if $string =~ /\A\z/ ;' 
perl -E 'my $string = "\n" . "baz\n\n" ; say "empty" if $string =~ /\S/ ;' 
+0

Dann gibt es 'if/\ A \ Z /' und 'if/\ A \ z /' ... die in verschiedenen Sprachen ziemlich konsistent sind [außer Python aber das ist ok] (http://stackoverflow.com/ Fragen/7063420/Perl-kompatibler-regulärer-Ausdruck-pcre-in-Python). –

+0

'Dies ist Perl 5, Version 22, Subversion 0 (v5.22.0) für amd64-freebsd' gebaut –

+1

Nicht im Zusammenhang mit Ihrer Kernfrage, aber' my $ string = "\ n", "foo \ n \ n" ' weist $ $ string eine einzelne neue Zeile zu. Der Rest ist wegen des Komma-Betreibers weggeworfen. – ThisSuitIsBlackNot

Antwort

2

/\p{IsBlank}/ prüft nicht, für eine leere Zeichenfolge. \p entspricht einem Zeichen mit der angegebenen Unicode-Eigenschaft.

$ unichars '\p{IsBlank}' | cat 
---- U+0009 CHARACTER TABULATION 
---- U+0020 SPACE 
---- U+00A0 NO-BREAK SPACE 
---- U+1680 OGHAM SPACE MARK 
---- U+2000 EN QUAD 
---- U+2001 EM QUAD 
---- U+2002 EN SPACE 
---- U+2003 EM SPACE 
---- U+2004 THREE-PER-EM SPACE 
---- U+2005 FOUR-PER-EM SPACE 
---- U+2006 SIX-PER-EM SPACE 
---- U+2007 FIGURE SPACE 
---- U+2008 PUNCTUATION SPACE 
---- U+2009 THIN SPACE 
---- U+200A HAIR SPACE 
---- U+202F NARROW NO-BREAK SPACE 
---- U+205F MEDIUM MATHEMATICAL SPACE 
---- U+3000 IDEOGRAPHIC SPACE 

Es passt " \n" seit SPACE die ISBLANK Eigenschaft hat.


/[[:blank:]]/ sucht nicht nach einer leeren Zeichenfolge. [...] entspricht einem Zeichen, das ein Mitglied der angegebenen Klasse ist.

$ unichars '[[:blank:]]' | cat 
---- U+0009 CHARACTER TABULATION 
---- U+0020 SPACE 
---- U+00A0 NO-BREAK SPACE 
---- U+1680 OGHAM SPACE MARK 
---- U+2000 EN QUAD 
---- U+2001 EM QUAD 
---- U+2002 EN SPACE 
---- U+2003 EM SPACE 
---- U+2004 THREE-PER-EM SPACE 
---- U+2005 FOUR-PER-EM SPACE 
---- U+2006 SIX-PER-EM SPACE 
---- U+2007 FIGURE SPACE 
---- U+2008 PUNCTUATION SPACE 
---- U+2009 THIN SPACE 
---- U+200A HAIR SPACE 
---- U+202F NARROW NO-BREAK SPACE 
---- U+205F MEDIUM MATHEMATICAL SPACE 
---- U+3000 IDEOGRAPHIC SPACE 

Sie paßt " \n" seit SPACE ein Mitglied der [:blank:] POSIX-Zeichenklasse ist und somit ein Mitglied der [[:blank:]] Zeichenklasse.

+0

Danke, beginnend zu grok ... seit '$ nonblank ++ if/\ P {IsBlank} /' (ohne die Anker) gibt mir "8" ('__DATA__' hat 8 Zeilen) Ich nehme an es zählt' \ n' als non-'{IsBlank}' (wegen '\ P') und sieht somit 8 Übereinstimmungen. Dann, als '/^\ P {IsBlank} $ /', basiert das Inkrementieren auf den drei Zeilen einzelner nicht-leerer horizontaler Zeichen ('\ n'), so dass ich" 3 "erhält. Aber '/ \ P {IsBlank}' gibt mir eine Zählung von "5", weil es fünf Zeilen mit '\ s'-Stil horizontale" Leerzeichen "gibt: die vier mit Text (und Leerzeichen zwischen Wörtern), und Zeile Nummer 5, die besteht aus '" "\ n" erscheint als leere Zeile. –