A veces quiero hacer coincidir espacios en blanco pero no nueva línea.
Hasta ahora he estado recurriendo [ \t]
. ¿Hay alguna manera menos incómoda?
A veces quiero hacer coincidir espacios en blanco pero no nueva línea.
Hasta ahora he estado recurriendo [ \t]
. ¿Hay alguna manera menos incómoda?
Respuestas:
Las versiones de Perl 5.10 y posteriores admiten clases de caracteres verticales y horizontales subsidiarias \v
y \h
, además, la clase de caracteres de espacio en blanco genérico\s
La solución más limpia es usar la clase de caracteres de espacio en blanco horizontal\h
. Esto coincidirá con la pestaña y el espacio del conjunto ASCII, el espacio sin interrupción del ASCII extendido o cualquiera de estos caracteres 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
El patrón de espacio vertical\v
es menos útil, pero coincide con estos caracteres.
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
Hay siete caracteres de espacio en blanco vertical que coinciden \v
y dieciocho caracteres horizontales que coinciden \h
. \s
coincide con veintitrés personajes
Todos los caracteres de espacio en blanco son verticales u horizontales sin superposición, pero no son subconjuntos adecuados porque \h
también coinciden con U + 00A0 ESPACIO SIN INTERRUPCIONES, y \v
también coinciden con U + 0085 LÍNEA SIGUIENTE, ninguno de los cuales coincide con\s
\h
funciona solo en los idiomas que admite PCRE
.
[[:blank:]]
no coincide con ninguna ruptura espacio--
o"\xA0"
\h
funcionó perfectamente para mi caso de uso, que estaba haciendo una búsqueda / reemplazo en Notepad ++ en 1 o más espacios contiguos de líneas no nuevas. Nada más (simple) funcionó.
\h
ligeramente no estándar es su inclusión MONGOLIAN VOWEL SEPARATOR
. Unicode no lo considera espacio en blanco. Por esa razón, Perl \h
difiere de POSIX blank
( [[:blank:]]
en Perl, \p{Blank}
en Java) y Java 8 \h
. Es cierto que es un caso extremo.
Use un doble negativo:
/[^\S\r\n]/
Es decir, no espacio en blanco (la S mayúscula se complementa) o no retorno de carro o no nueva línea. Distribuyendo el exterior no ( es decir , el complemento ^
en la clase de caracteres) con la ley de De Morgan , esto es equivalente a "espacio en blanco pero no retorno de carro o nueva línea". La inclusión de ambos \r
y \n
en el patrón maneja correctamente todas las convenciones de nueva línea de Unix (LF), Mac OS (CR) clásico y DOS-ish (CR LF) .
No es necesario tomar mi palabra:
#! /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";
}
Salida:
"" => coincidencia "\ f" => coincidencia "\ t" => coincidencia "\ r" => sin coincidencia "\ n" => sin coincidencia
Tenga en cuenta la exclusión de la pestaña vertical, pero esto se aborda en v5.18 .
Antes de objetar con demasiada dureza, la documentación de Perl usa la misma técnica. Una nota al pie en la sección "Espacio en blanco" de perlrecharclass lee
Antes de Perl v5.18,
\s
no coincidía con la pestaña vertical.[^\S\cK]
(oscuramente) coincide con lo que\s
tradicionalmente hacía.
La misma sección de perlrecharclass también sugiere otros enfoques que no ofenden la oposición de los profesores de idiomas a los negativos dobles.
Fuera de la configuración regional y las reglas Unicode o cuando el /a
cambio está en vigor, " \s
coincide [\t\n\f\r ]
y, comenzando en Perl v5.18, la pestaña vertical \cK
". Deseche \r
y \n
deje /[\t\f\cK ]/
para espacios en blanco coincidentes pero no para nueva línea.
Si su texto es Unicode, use un código similar al siguiente para construir un patrón de la tabla en la sección de documentación mencionada anteriormente .
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;
}
El truco doble negativo también es útil para hacer coincidir los caracteres alfabéticos. Recuerde que \w
coincide con "caracteres de palabras", caracteres alfabéticos y dígitos y guiones bajos. Los estadounidenses feos a veces queremos escribirlo como, digamos,
if (/[A-Za-z]+/) { ... }
pero una clase de caracteres doble negativa puede respetar la configuración regional:
if (/[^\W\d_]+/) { ... }
Expresar "un carácter de palabra pero no un dígito o guión bajo" de esta manera es un poco opaco. Una clase de caracteres POSIX comunica la intención más directamente
if (/[[:alpha:]]+/) { ... }
o con una propiedad Unicode como szbalint sugirió
if (/\p{Letter}+/) { ... }
\r
, por ejemplo, en Windows, por lo que considerar exluding los del partido, así: /[^\S\r\n]/
)
\h
está disponible.
Una variación de la respuesta de Greg que también incluye retornos de carro:
/[^\S\r\n]/
Esta expresión regular es más segura que /[^\S\n]/
con no \r
. Mi razonamiento es que Windows usa \r\n
para las nuevas líneas y Mac OS 9 \r
. Es poco probable que lo encuentres \r
sin \n
hoy en día, pero si lo encuentras, no podría significar nada más que una nueva línea. Por lo tanto, dado que \r
puede significar una nueva línea, también debemos excluirla.
La expresión regular a continuación coincidiría con espacios en blanco pero no con un nuevo carácter de línea.
(?:(?!\n)\s)
Si desea agregar el retorno de carro también, agregue \r
con el |
operador dentro de la búsqueda anticipada negativa.
(?:(?![\n\r])\s)
Agregue +
después del grupo sin captura para que coincida con uno o más espacios en blanco.
(?:(?![\n\r])\s)+
No sé por qué no mencionaron la clase de caracteres POSIX [[:blank:]]
que coincide con espacios en blanco horizontales ( espacios y tabulaciones ). Esta clase de caracteres POSIX funcionaría en BRE ( expresiones regulares básicas ), ERE ( expresión regular extendida ), PCRE ( expresión regular compatible con Perl ).
Lo que está buscando es la blank
clase de caracteres POSIX . En Perl se hace referencia como:
[[:blank:]]
en Java (no olvide habilitar UNICODE_CHARACTER_CLASS
):
\p{Blank}
En comparación con similares \h
, POSIX blank
es compatible con algunos motores regex más ( referencia ). Un beneficio importante es que su definición se fija en el Anexo C: Propiedades de compatibilidad de las expresiones regulares Unicode y estándar en todos los sabores de expresiones regulares que admiten Unicode. (En Perl, por ejemplo, \h
opta por incluir adicionalmente el MONGOLIAN VOWEL SEPARATOR
.) Sin embargo, un argumento a favor \h
es que siempre detecta los caracteres Unicode (incluso si los motores no están de acuerdo en cuál), mientras que las clases de caracteres POSIX a menudo son ASCII por defecto -solo (como en Java).
Pero el problema es que incluso apegarse a Unicode no resuelve el problema al 100%. Considere los siguientes caracteres que no se consideran espacios en blanco en Unicode:
SEPARADOR DE VOCALES MONGOLIANAS U + 180E
U + 200B ESPACIO ANCHO CERO
ANCHO CERO U + 200C SIN UNIÓN
UNIDAD DE ANCHO CERO U + 200D
U + 2060 WORD JOINER
U + FEFF ANCHO CERO ESPACIO SIN INTERRUPCIONES
Tomado de https://en.wikipedia.org/wiki/White-space_character
El mencionado separador de vocales de Mongolia no está incluido por lo que probablemente sea una buena razón. Esto, junto con 200C y 200D, se produce dentro de las palabras (AFAIK) y, por lo tanto, rompe la regla cardinal que todos los demás espacios en blanco obedecen: puede tokenizar con ella. Son más como modificadores. Sin embargo, ZERO WIDTH SPACE
, WORD JOINER
, y ZERO WIDTH NON-BREAKING SPACE
(si se utiliza como distinto de una marca de orden de bytes) ajustarse a la regla de los espacios en blanco en mi libro. Por lo tanto, los incluyo en mi clase de caracteres de espacio en blanco horizontal.
En Java:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
etiqueta en la pregunta original.
[\p{Blank}\u200b\u180e]
se requieren horrores como . Es cierto que tiene sentido que un separador de vocales no se considere un espacio en blanco, pero por qué el espacio de ancho cero no está en clases como \s
y \p{Blank}
, me gana.
m/ /g
solo dale espacio / /
y funcionará. O use \S
: reemplazará todos los caracteres especiales como tabulación, líneas nuevas, espacios, etc.
[\r\f]
.