Ich möchte manchmal Leerzeichen, aber keine Zeilenumbrüche verwenden.
Bisher habe ich darauf zurückgegriffen [ \t]
. Gibt es einen weniger unangenehmen Weg?
Ich möchte manchmal Leerzeichen, aber keine Zeilenumbrüche verwenden.
Bisher habe ich darauf zurückgegriffen [ \t]
. Gibt es einen weniger unangenehmen Weg?
Antworten:
Perl - Versionen 5.10 und höher unterstützen Tochter vertikale und horizontale Zeichenklassen, \v
und \h
sowie die allgemeine Leerzeichenklasse\s
Die sauberste Lösung besteht darin, die horizontale Leerzeichenzeichenklasse zu verwenden \h
. Dies entspricht der Registerkarte und dem Leerzeichen aus dem ASCII-Satz, dem nicht unterbrechenden Leerzeichen aus dem erweiterten ASCII-Satz oder einem dieser Unicode-Zeichen
U+0009 CHARACTER TABULATION
U+0020 SPACE
U+00A0 NO-BREAK SPACE (not matched by \s)
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
Das vertikale Raummuster \v
ist weniger nützlich, stimmt jedoch mit diesen Zeichen überein
U+000A LINE FEED
U+000B LINE TABULATION
U+000C FORM FEED
U+000D CARRIAGE RETURN
U+0085 NEXT LINE (not matched by \s)
U+2028 LINE SEPARATOR
U+2029 PARAGRAPH SEPARATOR
Es gibt sieben vertikale Leerzeichen, die übereinstimmen, \v
und achtzehn horizontale Leerzeichen , die übereinstimmen \h
. \s
entspricht dreiundzwanzig Zeichen
Alle Leerzeichen sind entweder vertikal oder horizontal ohne Überlappung, aber sie sind keine richtigen Teilmengen, da sie \h
auch mit U + 00A0 NO-BREAK SPACE und \v
U + 0085 NEXT LINE übereinstimmen, von denen keine übereinstimmen\s
\h
funktioniert nur in den unterstützten Sprachen PCRE
.
[[:blank:]]
passt nicht No-Break Space -
oder"\xA0"
\h
Ich möchte erwähnen, dass dies perfekt für meinen Anwendungsfall funktioniert hat, bei dem in Notepad ++ ein oder mehrere zusammenhängende Leerzeichen ohne neue Zeilen gefunden / ersetzt wurden. Sonst (einfach) hat nichts funktioniert.
\h
etwas unüblich macht, ist seine Einbeziehung von MONGOLIAN VOWEL SEPARATOR
. Unicode betrachtet es nicht als Leerzeichen. Aus diesem Grund unterscheidet sich Perl \h
von POSIX blank
( [[:blank:]]
in Perl, \p{Blank}
in Java) und Java 8 \h
. Zugegeben, es ist ein Randfall.
Verwenden Sie ein doppeltes Negativ:
/[^\S\r\n]/
Das heißt, kein Nicht-Leerzeichen (das Kapital S ergänzt) oder kein Wagenrücklauf oder kein Zeilenumbruch. Wenn Sie das äußere Nicht ( dh die Ergänzung ^
in der Zeichenklasse) mit De Morgans Gesetz verteilen, entspricht dies „Leerzeichen, aber nicht Wagenrücklauf oder Zeilenumbruch“. Wenn Sie beide \r
und \n
das Muster korrekt einschließen , werden alle Unline- (LF), klassischen Mac OS- (CR) und DOS- ish- (CR LF) Newline-Konventionen korrekt behandelt .
Ich brauche nicht mein Wort dafür zu nehmen:
#! /usr/bin/env perl
use strict;
use warnings;
use 5.005; # for qr//
my $ws_not_crlf = qr/[^\S\r\n]/;
for (' ', '\f', '\t', '\r', '\n') {
my $qq = qq["$_"];
printf "%-4s => %s\n", $qq,
(eval $qq) =~ $ws_not_crlf ? "match" : "no match";
}
Ausgabe:
"" => Übereinstimmung "\ f" => Übereinstimmung "\ t" => Übereinstimmung "\ r" => keine Übereinstimmung "\ n" => keine Übereinstimmung
Beachten Sie den Ausschluss der vertikalen Registerkarte, dies wird jedoch in Version 5.18 behandelt .
Bevor zu heftige Einwände erhoben werden, wird in der Perl-Dokumentation dieselbe Technik verwendet. Eine Fußnote im Abschnitt "Leerzeichen" der Perlrecharklasse lautet
Vor Perl v5.18
\s
stimmte die vertikale Registerkarte nicht überein.[^\S\cK]
(dunkel) entspricht dem, was\s
traditionell getan wurde.
Der gleiche Abschnitt der Perlrecharklasse schlägt auch andere Ansätze vor, die den Widerstand der Sprachlehrer gegen Doppel-Negative nicht verletzen .
Außerhalb der Gebietsschema- und Unicode-Regeln oder wenn der /a
Schalter aktiv ist, " \s
stimmt überein [\t\n\f\r ]
und ab Perl v5.18 mit der vertikalen Registerkarte \cK
". Verwerfen \r
und \n
verlassen, /[\t\f\cK ]/
um passende Leerzeichen, aber keine Zeilenumbrüche zu erhalten.
Wenn Ihr Text Unicode ist, verwenden Sie Code ähnlich dem folgenden Unter, um ein Muster aus der Tabelle im oben genannten Dokumentationsabschnitt zu erstellen .
sub ws_not_nl {
local($_) = <<'EOTable';
0x0009 CHARACTER TABULATION h s
0x000a LINE FEED (LF) vs
0x000b LINE TABULATION vs [1]
0x000c FORM FEED (FF) vs
0x000d CARRIAGE RETURN (CR) vs
0x0020 SPACE h s
0x0085 NEXT LINE (NEL) vs [2]
0x00a0 NO-BREAK SPACE h s [2]
0x1680 OGHAM SPACE MARK h s
0x2000 EN QUAD h s
0x2001 EM QUAD h s
0x2002 EN SPACE h s
0x2003 EM SPACE h s
0x2004 THREE-PER-EM SPACE h s
0x2005 FOUR-PER-EM SPACE h s
0x2006 SIX-PER-EM SPACE h s
0x2007 FIGURE SPACE h s
0x2008 PUNCTUATION SPACE h s
0x2009 THIN SPACE h s
0x200a HAIR SPACE h s
0x2028 LINE SEPARATOR vs
0x2029 PARAGRAPH SEPARATOR vs
0x202f NARROW NO-BREAK SPACE h s
0x205f MEDIUM MATHEMATICAL SPACE h s
0x3000 IDEOGRAPHIC SPACE h s
EOTable
my $class;
while (/^0x([0-9a-f]{4})\s+([A-Z\s]+)/mg) {
my($hex,$name) = ($1,$2);
next if $name =~ /\b(?:CR|NL|NEL|SEPARATOR)\b/;
$class .= "\\N{U+$hex}";
}
qr/[$class]/u;
}
Der doppelt negative Trick ist auch praktisch, um alphabetische Zeichen abzugleichen. Denken Sie daran, dass dies \w
mit „Wortzeichen“, alphabetischen Zeichen sowie Ziffern und Unterstrichen übereinstimmt . Wir hässlichen Amerikaner wollen es manchmal so schreiben, als ob
if (/[A-Za-z]+/) { ... }
Eine doppelt negative Zeichenklasse kann jedoch das Gebietsschema respektieren:
if (/[^\W\d_]+/) { ... }
Auf diese Weise „ein Wortzeichen, aber keine Ziffer oder Unterstrich“ auszudrücken, ist etwas undurchsichtig. Eine POSIX-Zeichenklasse kommuniziert die Absicht direkter
if (/[[:alpha:]]+/) { ... }
oder mit einer Unicode-Eigenschaft, wie von szbalint vorgeschlagen
if (/\p{Letter}+/) { ... }
\r
, zB unter Windows, so denken Sie daran auch diejenigen , die aus dem Spiel gewählte Art: /[^\S\r\n]/
)
\h
verfügbar ist.
Eine Variation von Gregs Antwort , die auch Wagenrückläufe enthält:
/[^\S\r\n]/
Diese Regex ist sicherer als /[^\S\n]/
mit Nr \r
. Meine Argumentation ist, dass Windows \r\n
für Zeilenumbrüche und Mac OS 9 verwendet \r
. Sie sind wahrscheinlich nicht finden , \r
ohne \n
heute, aber wenn Sie es finden, es könnte nicht gemein alles andere als eine neue Zeile. Da \r
dies eine neue Zeile bedeuten kann, sollten wir sie auch ausschließen.
Der unten stehende reguläre Ausdruck würde mit Leerzeichen übereinstimmen, jedoch nicht mit einem neuen Linienzeichen.
(?:(?!\n)\s)
Wenn Sie auch Wagenrücklauf hinzufügen möchten, fügen Sie \r
mit dem |
Operator innerhalb des negativen Lookaheads hinzu.
(?:(?![\n\r])\s)
Fügen Sie +
nach der Nicht-Erfassungsgruppe eines oder mehr Leerräume passen.
(?:(?![\n\r])\s)+
Ich weiß nicht, warum Sie die POSIX-Zeichenklasse, [[:blank:]]
die mit horizontalen Leerzeichen ( Leerzeichen und Tabulatoren ) übereinstimmt, nicht erwähnt haben . Diese POSIX-Chracter-Klasse funktioniert mit BRE ( Basic REgular Expressions ), ERE ( Extended Regular Expression ) und PCRE ( Perl Compatible Regular Expression ).
Was Sie suchen, ist die POSIX- blank
Zeichenklasse. In Perl wird darauf verwiesen als:
[[:blank:]]
in Java (nicht vergessen zu aktivieren UNICODE_CHARACTER_CLASS
):
\p{Blank}
Im Vergleich zu ähnlichen \h
wird POSIX blank
von einigen weiteren Regex-Engines unterstützt ( Referenz ). Ein Hauptvorteil besteht darin, dass seine Definition in Anhang C festgelegt ist: Kompatibilitätseigenschaften von regulären Unicode-Ausdrücken und Standard für alle Regex-Varianten, die Unicode unterstützen. (In Perl wird beispielsweise \h
zusätzlich das eingeschlossen MONGOLIAN VOWEL SEPARATOR
.) Ein Argument dafür \h
ist jedoch, dass immer Unicode-Zeichen erkannt werden (auch wenn sich die Engines nicht darüber einig sind), während POSIX-Zeichenklassen häufig standardmäßig ASCII sind -nur (wie in Java).
Das Problem ist jedoch, dass selbst das Festhalten an Unicode das Problem nicht zu 100% löst. Berücksichtigen Sie die folgenden Zeichen, die in Unicode nicht als Leerzeichen gelten:
U + FEFF NULL BREITE NICHT BRECHENDER RAUM
Entnommen aus https://en.wikipedia.org/wiki/White-space_character
Der oben erwähnte mongolische Vokaltrenner ist aus wahrscheinlich guten Gründen nicht enthalten. Es kommt zusammen mit 200C und 200D in Wörtern (AFAIK) vor und verstößt daher gegen die Grundregel, die alle anderen Leerzeichen befolgen: Sie können damit tokenisieren. Sie sind eher Modifikatoren. Allerdings ZERO WIDTH SPACE
, WORD JOINER
und ZERO WIDTH NON-BREAKING SPACE
(wenn es als etwas anderes als eine Byte-Reihenfolge - Marke verwendet wird ) paßt die Leerzeichen Regel in meinem Buch. Daher füge ich sie in meine horizontale Leerzeichen-Zeichenklasse ein.
In Java:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
Tag in der ursprünglichen Frage.
[\p{Blank}\u200b\u180e]
erforderlich sind. Zugegeben, es ist sinnvoll, dass ein Vokaltrennzeichen nicht als Leerzeichen betrachtet wird, aber warum Leerzeichen mit der Breite Null nicht in Klassen wie \s
und enthalten sind \p{Blank}
, schlägt mich.
m/ /g
Geben Sie einfach Platz / /
, und es wird funktionieren. Oder verwenden Sie \S
- es ersetzt alle Sonderzeichen wie Tabulatoren, Zeilenumbrüche, Leerzeichen usw.
[\r\f]
.