A volte voglio abbinare spazi bianchi ma non newline.
Finora ho fatto ricorso [ \t]
. C'è un modo meno imbarazzante?
A volte voglio abbinare spazi bianchi ma non newline.
Finora ho fatto ricorso [ \t]
. C'è un modo meno imbarazzante?
Risposte:
Le versioni Perl 5.10 e successive supportano le classi di caratteri orizzontali e verticali secondarie \v
e \h
, oltre alla classe di caratteri generici degli spazi bianchi\s
La soluzione più pulita è utilizzare la classe di caratteri degli spazi bianchi orizzontali\h
. Questo abbinerà tab e spazio dal set ASCII, spazio non interrotto da ASCII esteso o uno qualsiasi di questi caratteri 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
Il modello dello spazio verticale\v
è meno utile, ma corrisponde a questi caratteri
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
Esistono sette caratteri verticali bianchi che corrispondono \v
e diciotto orizzontali corrispondenti \h
. \s
corrisponde a 23 caratteri
Tutti i caratteri degli spazi bianchi sono verticali o orizzontali senza sovrapposizioni, ma non sono sottoinsiemi appropriati poiché \h
corrispondono anche a U + 00A0 NO-BREAK SPACE e \v
anche a U + 0085 NEXT LINE, nessuno dei quali è associato da\s
\h
funziona solo sulle lingue che supporta PCRE
.
[[:blank:]]
non corrisponde allo spazio no-break -
o"\xA0"
\h
funzionato perfettamente per il mio caso d'uso che stava facendo una ricerca / sostituzione in Notepad ++ su 1 o più spazi contigui non di nuova riga. Nient'altro (semplice) ha funzionato.
\h
leggermente non standard Perl è la sua inclusione MONGOLIAN VOWEL SEPARATOR
. Unicode non lo considera spazi bianchi. Per questo motivo, Perl \h
differisce da POSIX blank
( [[:blank:]]
in Perl, \p{Blank}
in Java) e Java 8 \h
. Certo, è un caso limite.
Usa un doppio negativo:
/[^\S\r\n]/
Cioè, non-non-spazi bianchi (i complementi di S maiuscoli) o non-trasporto-ritorno o non-newline. Distribuire l'esterno non ( cioè il complemento ^
nella classe personaggio) con la legge di De Morgan , questo equivale a "spazi bianchi ma non ritorno a capo o newline". Includere entrambi \r
e \n
nel modello gestisce correttamente tutte le convenzioni newline di Unix (LF), Mac OS (CR) e DOS-ish (CR LF) .
Non c'è bisogno di crederci sulla parola:
#! /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";
}
Produzione:
"" => corrispondenza "\ f" => match "\ t" => match "\ r" => nessuna corrispondenza "\ n" => nessuna corrispondenza
Nota l'esclusione della scheda verticale, ma questo è risolto nella v5.18 .
Prima di obiettare troppo duramente, la documentazione Perl utilizza la stessa tecnica. Si legge una nota a piè di pagina nella sezione "Spazio bianco" della perlrecharclass
Prima di Perl v5.18,
\s
non corrispondeva alla scheda verticale.[^\S\cK]
(oscuramente) corrisponde a ciò che\s
tradizionalmente faceva.
La stessa sezione di perlrecharclass suggerisce anche altri approcci che non offenderanno l'opposizione degli insegnanti di lingue ai doppi negativi.
Fuori dalle regole locali e Unicode o quando l' opzione /a
è attiva, " \s
corrisponde [\t\n\f\r ]
e, a partire da Perl v5.18, la scheda verticale \cK
". Scarta \r
e \n
di lasciare /[\t\f\cK ]/
per la corrispondenza spazi bianchi, ma non nuova riga.
Se il tuo testo è Unicode, utilizza un codice simile al sotto riportato di seguito per costruire un modello dalla tabella nella sezione della documentazione sopra menzionata .
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;
}
Il trucco a doppio negativo è utile anche per abbinare i caratteri alfabetici. Ricordate che \w
le partite “caratteri di parola”, caratteri alfabetici e cifre e underscore. Noi brutti americani a volte vogliamo scriverlo come, diciamo,
if (/[A-Za-z]+/) { ... }
ma una classe di caratteri a doppio negativo può rispettare la locale:
if (/[^\W\d_]+/) { ... }
Esprimere "un carattere parola ma non cifra o carattere di sottolineatura" in questo modo è un po 'opaco. Una classe di caratteri POSIX comunica l'intento più direttamente
if (/[[:alpha:]]+/) { ... }
o con una proprietà Unicode come suggerito da szbalint
if (/\p{Letter}+/) { ... }
\r
, ad esempio, su Windows, in modo da considerare esclusa la quelli della partita così: /[^\S\r\n]/
)
\h
è disponibile.
Una variazione sulla risposta di Greg che include anche i ritorni a capo:
/[^\S\r\n]/
Questa regex è più sicura che /[^\S\n]/
con no \r
. Il mio ragionamento è che Windows utilizza \r\n
per le newline e Mac OS 9 utilizzato \r
. È improbabile che lo trovi \r
senza \n
oggigiorno, ma se lo trovi, non potrebbe significare nient'altro che una nuova riga. Pertanto, poiché \r
può significare una nuova riga, dovremmo escluderla anche noi.
La regex di seguito corrisponderebbe agli spazi bianchi ma non di un nuovo carattere di linea.
(?:(?!\n)\s)
Se si desidera aggiungere anche il ritorno a capo, aggiungere \r
con l' |
operatore all'interno del punto di vista negativo.
(?:(?![\n\r])\s)
Aggiungi +
dopo il gruppo non acquisito per abbinare uno o più spazi bianchi.
(?:(?![\n\r])\s)+
Non so perché non avete menzionato la classe di caratteri POSIX [[:blank:]]
che corrisponde a qualsiasi spazio bianco orizzontale ( spazi e tabulazioni ). Questa classe di caratteri POSIX funzionerebbe su BRE ( espressioni regolari di base ), ERE ( espressione regolare estesa ), PCRE ( espressione regolare compatibile Perl ).
Quello che stai cercando è la blank
classe di caratteri POSIX . In Perl è indicato come:
[[:blank:]]
in Java (non dimenticare di abilitare UNICODE_CHARACTER_CLASS
):
\p{Blank}
Rispetto al simile \h
, POSIX blank
è supportato da alcuni motori regex in più ( riferimento ). Un grande vantaggio è che la sua definizione è fissata nell'Allegato C: Proprietà di compatibilità delle espressioni regolari Unicode e standard in tutti gli aromi regex che supportano Unicode. (In Perl, ad esempio, \h
sceglie di includere ulteriormente il MONGOLIAN VOWEL SEPARATOR
.) Tuttavia, un argomento a favore di \h
è che rileva sempre i caratteri Unicode (anche se i motori non sono d'accordo su quale), mentre le classi di caratteri POSIX sono spesso di default ASCII -solo (come in Java).
Ma il problema è che anche attenersi a Unicode non risolve il problema al 100%. Considera i seguenti caratteri che non sono considerati spazi bianchi in Unicode:
SEPARATORE VOCALE MONGOLIANO U + 180E
U + 200B SPAZIO DI LARGHEZZA ZERO
U + 200C ZERO WIDTH NON JOINER
U + 200D ZERO WIDTH JOINER
U + 2060 WORD JOINER
U + FEFF ZERO WIDTH SPAZIO NON INTERRUTTORE
Tratto da https://en.wikipedia.org/wiki/White-space_character
Il suddetto separatore vocale vocale mongolo non è incluso per quello che probabilmente è una buona ragione. Insieme a 200C e 200D, si presenta all'interno delle parole (AFAIK), e quindi infrange la regola cardinale a cui tutti gli altri spazi bianchi obbediscono: puoi tokenizzare con esso. Sono più come modificatori. Tuttavia, ZERO WIDTH SPACE
, WORD JOINER
, eZERO WIDTH NON-BREAKING SPACE
(se usato come diverso da un segno di ordine di byte) montare la regola spazio bianco nel mio libro. Pertanto, li includo nella mia classe di caratteri degli spazi bianchi orizzontali.
In Java:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
tag nella domanda originale.
[\p{Blank}\u200b\u180e]
sono richiesti orrori simili . Certo, ha senso che un separatore vocale non sia considerato un carattere di spazi bianchi, ma perché lo spazio a larghezza zero non è in classi come \s
e \p{Blank}
, mi batte.
m/ /g
lascia spazio / /
e funzionerà. Oppure usa \S
: sostituirà tutti i caratteri speciali come tab, newline, spazi e così via.
[\r\f]
.