Je veux parfois faire correspondre les espaces mais pas les nouvelles lignes.
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 les nouvelles lignes.
Jusqu'à présent, j'ai eu recours à [ \t]
. Y a-t-il un moyen moins gênant ?
Utilisez un double négatif :
/[^\S\r\n]/
C'est-à-dire, pas-pas-d'espace blanc (le S majuscule complète) ou pas-de-retour-de-chariot ou pas-de-nouvelle-ligne. La distribution du not extérieur ( c'est-à-dire le complément ^
dans la classe de caractères) avec La loi de Morgan cela équivaut à "espace blanc mais pas de retour chariot ni de nouvelle ligne". En incluant à la fois \r
y \n
dans le motif gère correctement tous les systèmes Unix (LF), Mac OS classique (CR) et DOS (CR LF). conventions relatives aux nouvelles lignes .
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";
}
Sortie :
" " => match
"\\f" => match
"\\t" => match
"\\r" => no match
"\\n" => no match
Notez l'exclusion de la tabulation verticale, mais ceci est abordé dans la v5.18 .
Avant d'objecter trop sévèrement, sachez que la documentation de Perl utilise la même technique. Une note de bas de page dans le document Section "Whitespace" de perlrecharclass lit
Avant la version 5.18 de Perl,
\s
ne correspondait pas à l'onglet vertical.[^\S\cK]
correspond (obscurément) à ce que\s
traditionnellement.
En même section de perlrecharclass suggère également d'autres approches qui ne heurteront pas l'opposition des professeurs de langues aux doubles négations.
En dehors des règles locales et de l'Unicode ou lorsque l'élément /a
est en vigueur, " \s
correspond à [\t\n\f\r ]
et, à partir de Perl v5.18, l'onglet vertical, \cK
." Jeter \r
y \n
de laisser /[\t\f\cK ]/
pour la correspondance des espaces mais pas des nouvelles lignes.
Si votre texte est en Unicode, utilisez un code similaire au sous ci-dessous pour construire un motif à 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 du double négatif est également pratique pour faire correspondre des caractères alphabétiques. Rappelez-vous que \w
correspond à des "caractères de mot", des caractères alphabétiques et les chiffres et les traits de soulignement. Nous, les vilains Américains, voulons parfois l'écrire comme, par exemple ,
if (/[A-Za-z]+/) { ... }
mais une classe de caractères double-négative peut respecter la locale :
if (/[^\W\d_]+/) { ... }
Exprimer "un caractère de mot mais pas un chiffre ou un trait de soulignement" de cette manière est un peu opaque. Une classe de caractères POSIX communique l'intention plus directement
if (/[[:alpha:]]+/) { ... }
ou avec une propriété Unicode comme szbalint Proposition de
if (/\p{Letter}+/) { ... }
Astucieux, mais le comportement est très surprenant, et je ne vois pas en quoi il est moins gênant.
Comment puis-je imbriquer cette expression dans une autre ? Par exemple, remplacer " \s
" avec elle dans /(\+|0|\()[\d()\s-]{6,20}\d/g
? Thx
Les versions 5.10 et ultérieures de Perl prennent en charge les classes de caractères verticaux et horizontaux subsidiaires, \v
y \h
ainsi que la classe de caractères d'espacement générique \s
La solution la plus propre est d'utiliser le espace blanc horizontal classe de caractères \h
. Cela correspondra à la tabulation et à l'espace du jeu 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
En espace vertical motif \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 caractères d'espacement vertical qui correspondent à \v
et dix-huit horizontaux qui correspondent \h
. \s
correspond à vingt-trois caractères
Tous les caractères d'espacement sont soit vertical o horizontal sans chevauchement, mais ce ne sont pas des sous-ensembles corrects car \h
correspond aussi à U+00A0 NO-BREAK SPACE, et \v
correspond également à U+0085 NEXT LINE, qui ne sont pas pris en compte par l'option \s
@AleksandrDubinsky cette notation POSIX vide [[:blank:]]
fonctionnera dans la plupart des langues.
Une variation sur La réponse de Greg qui inclut également les retours de chariot :
/[^\S\r\n]/
Cette regex est plus sûre que /[^\S\n]/
sans \r
. Mon raisonnement est que Windows utilise \r\n
pour les nouvelles lignes, et Mac OS 9 utilisait \r
. Vous avez peu de chances de trouver \r
sans \n
de nos jours, mais si vous le trouvez, il ne peut signifier autre chose qu'une nouvelle ligne. Ainsi, depuis \r
peut signifier une nouvelle ligne, nous devrions l'exclure également.
Vous pourriez être surpris de voir combien de programmes utilisent encore " \r "pour les fins de ligne. Il m'a fallu parfois un certain temps pour comprendre que mon problème était que le fichier utilisait ces éléments. Ou qu'il utilisait le codage de caractères MacRoman...
La regex ci-dessous correspondrait aux espaces blancs mais pas au caractère de nouvelle ligne.
(?:(?!\n)\s)
Si vous voulez ajouter le retour de chariot aussi, alors ajoutez \r
avec le |
à l'intérieur du lookahead négatif.
(?:(?![\n\r])\s)
Ajouter +
après le groupe non capturant pour correspondre à un ou plusieurs espaces blancs.
(?:(?![\n\r])\s)+
Je ne sais pas pourquoi vous avez oublié de mentionner la classe de caractères POSIX. [[:blank:]]
qui correspond à tous les espaces horizontaux ( espaces et tabulations ). Cette classe de chractère POSIX fonctionnerait sur BRE( Expressions rationnelles de base ), ERE( Expression régulière étendue ), PCRE( Expression régulière compatible avec Perl ).
Ce que vous cherchez, c'est le POSIX blank
classe de caractères. En Perl, elle est référencée comme :
[[:blank:]]
en Java (n'oubliez pas d'activer UNICODE_CHARACTER_CLASS
):
\p{Blank}
Par rapport à des \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 en Annexe C : Propriétés de compatibilité des expressions régulières Unicode et standard dans toutes les saveurs de regex qui supportent Unicode. (En Perl, par exemple, \h
choisit d'inclure en plus le MONGOLIAN VOWEL SEPARATOR
.) Cependant, un argument en faveur de \h
est qu'il détecte toujours les caractères Unicode (même si les moteurs ne sont pas d'accord sur lesquels), alors que les classes de caractères POSIX sont souvent par défaut uniquement ASCII (comme dans Java).
Mais le problème est que même en s'en tenant à Unicode, le problème n'est pas résolu à 100%. Considérez les caractères suivants qui ne sont pas considérés comme des espaces blancs dans Unicode :
U+180E SÉPARATEUR DE VOYELLES MONGOLIEN
U+200B ESPACE DE LARGEUR NULLE
U+200C LARGEUR ZÉRO NON-JOINTEUR
U+200D JOINTURE DE LARGEUR NULLE
U+2060 JOINTURE DES MOTS
U+FEFF ESPACE INSÉCABLE DE LARGEUR ZÉRO
Tiré de <a href="https://en.wikipedia.org/wiki/White-space_character" rel="noreferrer">https://en.wikipedia.org/wiki/White-space_character</a>
Le séparateur de voyelles mongolien mentionné plus haut n'est pas inclus pour ce qui est probablement une bonne raison. Il, ainsi que 200C et 200D, se trouvent à l'intérieur des mots (AFAIK), et donc enfreint la règle cardinale à laquelle tous les autres espaces blancs obéissent : vous pouvez les utiliser pour la tokénisation. Ce sont plutôt des modificateurs. Cependant, ZERO WIDTH SPACE
, WORD JOINER
y ZERO WIDTH NON-BREAKING SPACE
(s'ils sont utilisés autrement que comme marque d'ordre d'octet) correspondent à la règle de l'espace blanc dans mon livre. Par conséquent, je les inclus dans ma classe de caractères d'espacement horizontal.
En Java :
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
Vous devez ajouter les drapeaux de compilation de regexp appropriés à la compilation Java, et utiliser Java 7 ou une version ultérieure. Quoi qu'il en soit, la question ne portait pas du tout sur Java ou PCRE, donc tout cela est sans importance.
@tchrist Merci d'avoir signalé ce point. Je vais mettre à jour ma réponse. Je ne suis pas d'accord, cependant, pour dire que ma réponse n'est pas pertinente. Ce qui est immatériel, c'est le perl
dans la question originale.
@AleksandrDubinsky, \p {Blank} n'est pas pris en charge par JavaScript, et n'est donc pas "standard pour tous les types de regex" -1
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
5 votes
D'ailleurs, ces caractères sont aussi des "espaces blancs" :
[\r\f]
.2 votes
@eugeney, est-ce que quelqu'un fait encore de l'alimentation par formulaire ? ( \f 's)
1 votes
@AranMulholland : Tous ceux qui ont une imprimante orientée caractères. La plupart des imprimantes disposent d'un mode caractère ainsi que de PostScript ou d'un autre nom pour l'interface Hewlett Packard, et pour lancer une page, il faut envoyer un flux de formulaires.
1 votes
@Borodin Celui de Hewlett Packard s'appelle PCL (Printer Control Language).