Je veux parfois faire correspondre les espaces, mais pas la nouvelle ligne.
Jusqu'à présent, j'ai eu recours à [ \t]
. Y a-t-il un moyen moins gênant?
Je veux parfois faire correspondre les espaces, mais pas la nouvelle ligne.
Jusqu'à présent, j'ai eu recours à [ \t]
. Y a-t-il un moyen moins gênant?
Réponses:
Perl versions 5.10 et plus tard filiale de soutien des classes de caractères vertical et horizontal, \v
et \h
, ainsi que la classe de caractère générique des espaces\s
La solution la plus propre consiste à utiliser la classe de caractères des espaces blancs horizontaux\h
. Cela correspondra à l'onglet et à l'espace de l'ensemble ASCII, à l'espace insécable de l'ASCII étendu ou à l'un de ces caractères 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
Le motif d' espace vertical\v
est moins utile, mais correspond à ces caractères
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
Il y a sept espaces blancs verticaux qui correspondent \v
et dix-huit caractères horizontaux qui correspondent \h
. \s
correspond à vingt-trois caractères
Tous les caractères d'espacement sont verticaux ou horizontaux sans chevauchement, mais ils ne sont pas des sous-ensembles appropriés car ils \h
correspondent également à U + 00A0 NO-BREAK SPACE et \v
correspondent également à U + 0085 NEXT LINE, aucun des deux ne correspondant à\s
\h
ne fonctionne que sur les langues prises en charge PCRE
.
[[:blank:]]
cela ne correspond pas à l'espace insécable -
ou"\xA0"
\h
Je veux mentionner que cela a parfaitement fonctionné pour mon cas d'utilisation qui faisait une recherche / remplacement dans Notepad ++ sur 1 ou plusieurs espaces non-new-line contigus. Rien d'autre (simple) n'a fonctionné.
\h
légèrement non standard, c'est son inclusion de MONGOLIAN VOWEL SEPARATOR
. Unicode ne le considère pas comme un espace. Pour cette raison, Perl \h
diffère de POSIX blank
( [[:blank:]]
en Perl, \p{Blank}
en Java) et Java 8 \h
. Certes, c'est un cas de bord.
Utilisez un double négatif:
/[^\S\r\n]/
C'est-à-dire, pas-pas-blanc (le S majuscule complète) ou pas-retour-chariot ou pas-newline. Distribuer le non externe ( c'est-à - dire le complément ^
dans la classe de caractères) avec la loi de De Morgan , cela équivaut à "des espaces mais pas un retour chariot ou une nouvelle ligne". L'inclusion des deux \r
et \n
dans le modèle gère correctement toutes les conventions de nouvelle ligne Unix (LF), Mac OS (CR) et DOS-ish (CR LF) .
Pas besoin de me croire sur parole:
#! /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";
}
Production:
"" => correspond "\ f" => correspond "\ t" => correspond "\ r" => aucune correspondance "\ n" => aucune correspondance
Notez l'exclusion de l'onglet vertical, mais cela est traité dans la v5.18 .
Avant de trop objecter, la documentation Perl utilise la même technique. Une note de bas de page dans la section «Espace blanc» de perlrecharclass indique
Avant Perl v5.18,
\s
ne correspondait pas à l'onglet vertical.[^\S\cK]
(obscurément) correspond à ce qui\s
se faisait traditionnellement.
La même section de perlrecharclass suggère également d'autres approches qui n'offenseront pas l'opposition des professeurs de langue aux doubles négatifs.
En dehors des règles locales et Unicode ou lorsque le /a
commutateur est en vigueur, " \s
correspond [\t\n\f\r ]
et, à partir de Perl v5.18, l'onglet vertical, \cK
". Jeter \r
et \n
laisser /[\t\f\cK ]/
pour les espaces correspondants, mais pas pour les retours à la ligne.
Si votre texte est Unicode, utilisez un code similaire au sous-code ci-dessous pour construire un modèle à partir du tableau dans la section de documentation susmentionnée .
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;
}
L'astuce à double négatif est également pratique pour faire correspondre les caractères alphabétiques. N'oubliez pas que cela \w
correspond à des «caractères de mots», des caractères alphabétiques et des chiffres et un soulignement. Nous, les moches américains, voulons parfois l'écrire comme, disons,
if (/[A-Za-z]+/) { ... }
mais une classe de caractères à double négatif peut respecter les paramètres régionaux:
if (/[^\W\d_]+/) { ... }
Exprimer «un caractère de mot mais pas un chiffre ou un trait de soulignement» de cette façon est un peu opaque. Une classe de caractères POSIX communique l'intention plus directement
if (/[[:alpha:]]+/) { ... }
ou avec une propriété Unicode comme suggéré par szbalint
if (/\p{Letter}+/) { ... }
\r
, par exemple , sous Windows, alors pensez à ceux du compte non tenu de match ainsi: /[^\S\r\n]/
)
\h
est disponible.
Une variation de la réponse de Greg qui inclut également les retours chariot:
/[^\S\r\n]/
Ce regex est plus sûr que /[^\S\n]/
non \r
. Mon raisonnement est que Windows utilise \r\n
pour les retours à la ligne et Mac OS 9 utilisé \r
. Il est peu probable que vous trouviez \r
sans de \n
nos jours, mais si vous le trouvez, cela ne pourrait pas signifier autre chose qu'une nouvelle ligne. Ainsi, puisque \r
peut signifier une nouvelle ligne, nous devons également l'exclure.
Le regex ci-dessous correspondrait aux espaces blancs mais pas à un nouveau caractère de ligne.
(?:(?!\n)\s)
Si vous souhaitez également ajouter le retour chariot, ajoutez-le \r
avec l' |
opérateur à l'intérieur de l'anticipation négative.
(?:(?![\n\r])\s)
Ajoutez +
après le groupe non capturé pour faire correspondre un ou plusieurs espaces blancs.
(?:(?![\n\r])\s)+
Je ne sais pas pourquoi vous avez omis de mentionner la classe de caractères POSIX [[:blank:]]
qui correspond aux espaces blancs horizontaux ( espaces et tabulations ). Cette classe chrérique POSIX fonctionnerait sur BRE ( Expressions régulières de base ), ERE ( Expression régulière étendue ), PCRE ( Expression régulière compatible Perl ).
Ce que vous recherchez, c'est la blank
classe de caractères POSIX . En Perl, il est référencé comme:
[[:blank:]]
en Java (n'oubliez pas d'activer UNICODE_CHARACTER_CLASS
):
\p{Blank}
Comparé au similaire \h
, POSIX blank
est supporté par quelques moteurs regex supplémentaires ( référence ). Un avantage majeur est que sa définition est fixée dans l' Annexe C: Propriétés de compatibilité des expressions régulières Unicode et standard dans toutes les versions regex qui prennent en charge Unicode. (En Perl, par exemple, \h
choisit d'inclure en plus le MONGOLIAN VOWEL SEPARATOR
.) Cependant, un argument en faveur de cela \h
est qu'il détecte toujours les caractères Unicode (même si les moteurs ne sont pas d'accord sur lequel), tandis que les classes de caractères POSIX sont souvent par défaut ASCII -seulement (comme en Java).
Mais le problème est que même s'en tenir à Unicode ne résout pas le problème à 100%. Considérez les caractères suivants qui ne sont pas considérés comme des espaces dans Unicode:
SÉPARATEUR DE VOIX MONGOLES U + 180E
U + 200B ZERO WIDTH SPACE
U + 200C ZERO WIDTH NON-JOINER
JOINTEUR U + 200D ZERO WIDTH
JOIGNEUR DE MOT U + 2060
ESPACE NON-RUPTURE U + FEFF ZERO WIDTH
Le séparateur de voyelles mongole susmentionné n'est pas inclus pour ce qui est probablement une bonne raison. Il, avec 200C et 200D, se produit dans les mots (AFAIK), et brise donc la règle cardinale que tous les autres espaces obéissent: vous pouvez en faire un tokenize. Ils ressemblent plus à des modificateurs. Cependant, ZERO WIDTH SPACE
, WORD JOINER
et ZERO WIDTH NON-BREAKING SPACE
(si elle utilisé comme autre qu'une marque d'ordre d'octet) s'adapter à la règle des espaces dans mon livre. Par conséquent, je les inclue dans ma classe de caractères d'espaces blancs horizontaux.
En Java:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
balise de la question d'origine.
[\p{Blank}\u200b\u180e]
sont nécessaires. Certes, il est logique qu'un séparateur de voyelles ne soit pas considéré comme un espace blanc, mais pourquoi l'espace de largeur nulle n'est pas dans des classes comme \s
et \p{Blank}
, me bat.
m/ /g
donnez juste de l'espace / /
, et cela fonctionnera. Ou utilisez \S
- il remplacera tous les caractères spéciaux tels que tabulation, sauts de ligne, espaces, etc.
[\r\f]
.