Czasami chcę dopasować białe znaki, ale nie nową linię.
Do tej pory uciekałem się [ \t]
. Czy istnieje mniej niezręczny sposób?
Czasami chcę dopasować białe znaki, ale nie nową linię.
Do tej pory uciekałem się [ \t]
. Czy istnieje mniej niezręczny sposób?
Odpowiedzi:
Perl wersje 5.10 i później zależne wsparcie klas postaci pionowej i poziomej, \v
a \h
, jak również ogólny spacje klasa znaków\s
Najczystszym rozwiązaniem jest użycie poziomej klasy znaków białych znaków \h
. Spowoduje to dopasowanie tabulacji i spacji z zestawu ASCII, nierozdzielania spacji z rozszerzonego ASCII lub dowolnego z tych znaków Unicode
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
Pionowa przestrzeń wzór \v
jest mniej przydatna, ale pasuje do tych znaków
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
Istnieje siedem pasujących znaków pionowych białych znaków \v
i osiemnaście pasujących znaków poziomych \h
. \s
dopasowuje dwadzieścia trzy znaki
Wszystkie znaki białych znaków są pionowe lub poziome, bez nakładania się, ale nie są odpowiednimi podzestawami, ponieważ \h
również pasują do U + 00A0 BEZ PRZERWU, a \v
także pasują do U + 0085 NASTĘPNA LINIA, z których żaden nie jest dopasowany\s
\h
działa tylko w obsługiwanych językach PCRE
.
[[:blank:]]
nie pasuje do spacji bez przerwy -
lub"\xA0"
\h
działało idealnie w moim przypadku użycia, który szukał / zamienił w Notepad ++ na co najmniej 1 ciągłym spacji nie nowej linii. Nic innego (proste) nie działało.
\h
nieco niestandardowy, to jego włączenie MONGOLIAN VOWEL SEPARATOR
. Unicode nie uważa tego za spację. Z tego powodu Perl \h
różni się od POSIX blank
( [[:blank:]]
w Perlu, \p{Blank}
w Javie) i Java 8 \h
. Trzeba przyznać, że to przypadek na krawędzi.
Użyj podwójnie ujemnego:
/[^\S\r\n]/
Oznacza to, że nie-spacja (duża litera S uzupełnia) lub zwrot-przewóz lub brak nowej linii. Dystrybucja zewnętrzna nie ( tj . Uzupełniająca^
w klasie postaci) z prawem De Morgana , jest to równoważne z „białymi spacjami, ale nie znakiem powrotu karetki lub znakiem nowej linii”. Włączenie zarówno wzorca, jak \r
i \n
wzorca poprawnie obsługuje wszystkie konwencje nowego wiersza Uniksa (LF), klasycznego Mac OS (CR) i DOS-ish (CR LF) .
Nie musisz mi wierzyć na słowo:
#! /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";
}
Wynik:
„” => dopasowanie „\ f” => dopasowanie „\ t” => dopasowanie „\ r” => brak dopasowania „\ n” => brak dopasowania
Zwróć uwagę na wyłączenie karty pionowej, ale zostało to rozwiązane w wersji 5.18 .
Przed zbyt surowym sprzeciwem dokumentacja Perla używa tej samej techniki. Przypis w sekcji „Białe znaki” w perlrecharclass brzmi:
W wersjach wcześniejszych niż Perl v5.18
\s
nie pasował do zakładki pionowej.[^\S\cK]
(niejasno) pasuje do tego, co\s
tradycyjnie robiono.
Ta sama sekcja perlrecharclass sugeruje również inne podejścia, które nie obrażą sprzeciwu nauczycieli języków obcych przed podwójnymi negatywami.
Poza regułami ustawień regionalnych i Unicode lub gdy /a
przełącznik działa, „ \s
pasuje [\t\n\f\r ]
i, począwszy od Perla v5.18, pionowa karta \cK
”. Odrzuć \r
i \n
pozostaw, /[\t\f\cK ]/
aby dopasować białe znaki, ale nie nową linię.
Jeśli twój tekst to Unicode, użyj kodu podobnego do podanego poniżej, aby zbudować wzór z tabeli w wyżej wymienionej sekcji dokumentacji .
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;
}
Sztuczka podwójnie ujemna jest również przydatna do dopasowywania znaków alfabetycznych. Pamiętaj, że \w
pasuje do „znaków słownych”, znaków alfabetycznych oraz cyfr i podkreślników. My, brzydcy Amerykanie, czasami chcemy to napisać, powiedzmy,
if (/[A-Za-z]+/) { ... }
ale podwójnie ujemna klasa znaków może respektować ustawienia regionalne:
if (/[^\W\d_]+/) { ... }
Wyrażenie „znak słowa, ale nie cyfry lub podkreślenia” w ten sposób jest nieco nieprzejrzyste. Klasa znaków POSIX komunikuje zamiar bardziej bezpośrednio
if (/[[:alpha:]]+/) { ... }
lub z właściwością Unicode, jak sugerował szbalint
if (/\p{Letter}+/) { ... }
\r
, np na Windows, więc uważają, najtańsza te z meczu jak dobrze: /[^\S\r\n]/
)
\h
jest ono dostępne.
Odmiana odpowiedzi Grega, która obejmuje również zwrot karetki:
/[^\S\r\n]/
Ten wyrażenie regularne jest bezpieczniejsze niż /[^\S\n]/
bez \r
. Moje rozumowanie jest takie, że Windows używa \r\n
nowych linii, a Mac OS 9 używany \r
. Jest mało prawdopodobne, aby znaleźć \r
bez \n
dzisiejszych czasach, ale jeśli nie znajdziesz, to nie może oznaczać niczego oprócz znaku nowej linii. Zatem, ponieważ \r
może oznaczać nowy wiersz, powinniśmy go również wykluczyć.
Poniższy regex pasowałby do białych spacji, ale nie do nowego znaku linii.
(?:(?!\n)\s)
Jeśli chcesz również dodać znak powrotu karetki, dodaj go \r
wraz z |
operatorem wewnątrz przeczącej perspektywy.
(?:(?![\n\r])\s)
Dodaj +
po grupie, która nie została przechwycona, aby dopasować jedną lub więcej białych spacji.
(?:(?![\n\r])\s)+
Nie wiem, dlaczego ludzie nie wspomnieli o klasie znaków POSIX, [[:blank:]]
która pasuje do poziomych białych znaków ( spacji i tabulatorów ). Ta klasa chracter POSIX będzie działać na BRE ( Basic REgular Expressions ), ERE ( Extended Regular Expression ), PCRE ( Perl Compatible Regular Expression ).
To, czego szukasz, to blank
klasa znaków POSIX . W Perlu jest określany jako:
[[:blank:]]
w Javie (nie zapomnij włączyć UNICODE_CHARACTER_CLASS
):
\p{Blank}
W porównaniu z podobnym \h
, POSIX blank
jest obsługiwany przez kilka kolejnych silników wyrażeń regularnych ( odniesienie ). Główną zaletą jest to, że jego definicja została ustalona w załączniku C: Właściwości kompatybilności wyrażeń regularnych Unicode i standard we wszystkich odmianach regularnych obsługujących Unicode. (Na przykład w Perlu \h
decyduje się dodatkowo dołączyć MONGOLIAN VOWEL SEPARATOR
.) Jednak argumentem przemawiającym za \h
tym jest to, że zawsze wykrywa znaki Unicode (nawet jeśli silniki nie zgadzają się co do tego), podczas gdy klasy znaków POSIX są często domyślnie ASCII -tylko (jak w Javie).
Problem polega jednak na tym, że nawet trzymanie się Unicode nie rozwiązuje problemu w 100%. Rozważ następujące znaki, które nie są uważane za białe znaki w Unicode:
U + 180E MONGOLIJSKI SEPARATOR GŁÓWNY
U + 200B ZERO WIDTH SPACE
U + 200C SZEROKOŚĆ ZEROWA NIE JOINER
ŁĄCZNIK SZEROKOŚCI U + 200D
U + 2060 WORD JOINER
U + FEFF ZERO WIDTH PRZESTRZEŃ NIEWYŁUSZAJĄCA
Zaczerpnięte z https://en.wikipedia.org/wiki/White-space_character
Wyżej wymieniony mongolski separator samogłosek nie jest zawarty z tego, co prawdopodobnie jest dobrym powodem. Wraz z 200C i 200D występuje w słowach (AFAIK), a zatem łamie kardynalną zasadę, której przestrzegają wszystkie inne białe znaki: możesz za jej pomocą tokenizować. Są bardziej jak modyfikatory. Jednak ZERO WIDTH SPACE
, WORD JOINER
orazZERO WIDTH NON-BREAKING SPACE
(jeśli jest stosowany jako inny niż znak kolejności bajtów) pasuje do reguły białe znaki w mojej książce. Dlatego włączam je do mojej poziomej klasy białych znaków.
W Javie:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
znacznik w pierwotnym pytaniu.
[\p{Blank}\u200b\u180e]
wymagane są horrory . Trzeba przyznać, że separator samogłosek nie jest uważany za znak spacji, ale dlaczego nie ma spacji o zerowej szerokości w klasach takich jak \s
i \p{Blank}
, bije mnie.
m/ /g
po prostu daj miejsce / /
, a zadziała. Lub użyj \S
- zastąpi wszystkie znaki specjalne, takie jak tabulator, znaki nowej linii, spacje i tak dalej.
[\r\f]
.