Às vezes, eu quero combinar espaço em branco, mas não nova linha.
Até agora eu tenho recorrido [ \t]
. Existe uma maneira menos estranha?
Às vezes, eu quero combinar espaço em branco, mas não nova linha.
Até agora eu tenho recorrido [ \t]
. Existe uma maneira menos estranha?
Respostas:
As versões 5.10 e posteriores do Perl suportam classes de caracteres verticais e horizontais subsidiárias \v
e \h
, assim como a classe de caracteres de espaço em branco genérica\s
A solução mais limpa é usar a classe de caracteres de espaço em branco horizontal\h
. Isso corresponderá a tabulação e espaço do conjunto ASCII, espaço ininterrupto do ASCII estendido ou qualquer um desses 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
O padrão de espaço vertical\v
é menos útil, mas corresponde a esses 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
Existem sete caracteres de espaço em branco verticais que correspondem \v
e dezoito caracteres horizontais que correspondem \h
. \s
corresponde a vinte e três caracteres
Todos os caracteres de espaço em branco são verticais ou horizontais, sem sobreposição, mas não são subconjuntos adequados porque \h
também correspondem a U + 00A0 NO-BREAK ESPAÇO e \v
também correspondem a U + 0085 NEXT LINE, nenhum dos quais corresponde a\s
\h
funciona apenas nos idiomas suportados PCRE
.
[[:blank:]]
não corresponde ao espaço sem interrupção -
ou"\xA0"
\h
funcionou perfeitamente para o meu caso de uso, que estava encontrando / substituindo no Notepad ++ em 1 ou mais espaços contíguos que não são de nova linha. Nada mais (simples) funcionou.
\h
pouco fora do padrão é sua inclusão MONGOLIAN VOWEL SEPARATOR
. Unicode não considera espaço em branco. Por esse motivo, o Perl \h
difere do POSIX blank
( [[:blank:]]
no Perl, \p{Blank}
no Java) e do Java 8 \h
. É certo que é um caso de ponta.
Use um negativo duplo:
/[^\S\r\n]/
Ou seja, não-espaço em branco (o capital S complementa) ou não-retorno de carro ou não-nova linha. Distribuir o não externo ( isto é , o complemento ^
na classe de personagem) com a lei de De Morgan , é equivalente a "espaço em branco, mas não retorno de carro ou nova linha". A inclusão de ambos \r
e \n
no padrão manipula corretamente todas as convenções de nova linha do Unix (LF), Mac OS (CR) clássico e DOS-ish (CR LF) .
Não há necessidade de aceitar minha palavra:
#! /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";
}
Resultado:
"" => correspondência "\ f" => correspondência "\ t" => correspondência "\ r" => sem correspondência "\ n" => sem correspondência
Observe a exclusão da guia vertical, mas isso é abordado na v5.18 .
Antes de objetar com muita severidade, a documentação do Perl usa a mesma técnica. Uma nota de rodapé na seção "Espaço em branco" da perlrecharclass lê
Antes do Perl v5.18,
\s
não correspondia à guia vertical.[^\S\cK]
(obscuramente) corresponde ao que\s
tradicionalmente fazia.
A mesma seção da perlrecharclass também sugere outras abordagens que não ofendem a oposição dos professores de línguas aos negativos duplos.
Fora das regras de código de idioma e Unicode ou quando a /a
opção estiver em vigor, " \s
corresponde [\t\n\f\r ]
e, a partir do Perl v5.18, a guia vertical \cK
". Descarte \r
e \n
deixe o /[\t\f\cK ]/
espaço em branco correspondente, mas não a nova linha.
Se o seu texto for Unicode, use um código semelhante ao sub abaixo para construir um padrão a partir da tabela na seção de documentação mencionada acima .
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;
}
O truque de negativo duplo também é útil para combinar caracteres alfabéticos também. Lembre-se de que \w
corresponde a "caracteres da palavra", caracteres e dígitos alfabéticos e sublinhado. Nós, americanos feios, às vezes queremos escrever como, digamos,
if (/[A-Za-z]+/) { ... }
mas uma classe de caracteres dupla negativa pode respeitar o código do idioma:
if (/[^\W\d_]+/) { ... }
Expressar "um caractere de palavra, mas não um dígito ou sublinhado" dessa maneira é um pouco opaco. Uma classe de caracteres POSIX comunica a intenção mais diretamente
if (/[[:alpha:]]+/) { ... }
ou com uma propriedade Unicode, conforme sugerido pelo szbalint
if (/\p{Letter}+/) { ... }
\r
, por exemplo, no Windows, por isso considero exluding aqueles do jogo, bem como: /[^\S\r\n]/
)
\h
estiver disponível.
Uma variação na resposta de Greg que também inclui retornos de carro:
/[^\S\r\n]/
Esse regex é mais seguro do que /[^\S\n]/
sem \r
. Meu raciocínio é que o Windows usa \r\n
para novas linhas e o Mac OS 9 usado \r
. Você é improvável encontrar \r
sem \n
nos dias de hoje, mas se você encontrá-lo, ele não podia nada média, mas uma nova linha. Assim, como \r
pode significar uma nova linha, devemos excluí-la também.
O regex abaixo corresponderia a espaços em branco, mas não a um novo caractere de linha.
(?:(?!\n)\s)
Se você deseja adicionar retorno de carro também, adicione \r
o |
operador dentro da cabeça negativa.
(?:(?![\n\r])\s)
Adicione +
depois do grupo que não captura para corresponder a um ou mais espaços em branco.
(?:(?![\n\r])\s)+
Não sei por que as pessoas falharam em mencionar a classe de caracteres POSIX [[:blank:]]
que corresponde a qualquer espaço em branco horizontal ( espaços e tabulações ). Essa classe chracter POSIX funcionaria em BRE ( Expressões regulares regulares ), ERE ( Expressão regular estendida ), PCRE ( Expressão regular compatível com Perl ).
O que você está procurando é a blank
classe de caracteres POSIX . No Perl, é referenciado como:
[[:blank:]]
em Java (não se esqueça de ativar UNICODE_CHARACTER_CLASS
):
\p{Blank}
Comparado com o similar \h
, o POSIX blank
é suportado por mais alguns mecanismos regex ( referência ). Um benefício importante é que sua definição é fixada no Anexo C: Propriedades de Compatibilidade de Expressões Regulares Unicode e padrão em todos os tipos de expressões regulares que suportam Unicode. (No Perl, por exemplo, \h
escolhe incluir adicionalmente o MONGOLIAN VOWEL SEPARATOR
.) No entanto, um argumento a favor \h
é que ele sempre detecta caracteres Unicode (mesmo que os mecanismos não concordem com quais), enquanto as classes de caracteres POSIX geralmente são ASCII padrão. -só (como em Java).
Mas o problema é que mesmo a adesão ao Unicode não resolve o problema 100%. Considere os seguintes caracteres que não são considerados espaços em branco no Unicode:
SEPARADOR MONGOLIANO DE VOWEL U + 180E
ESPAÇO ZERO DA LARGURA DE U + 200B
NÃO-ARTICULADOR COM LARGURA ZERO U + 200C
JUNTA DE LARGURA ZERO U + 200D
JOINADOR DE PALAVRAS U + 2060
ESPAÇO U + FEFF ZERO LARGURA QUE NÃO SE VIRA
Retirado de https://en.wikipedia.org/wiki/White-space_character
O separador de vogais mongol mencionado acima não está incluído pelo que provavelmente é um bom motivo. Juntamente com 200C e 200D, ocorre dentro de palavras (AFAIK) e, portanto, quebra a regra principal que todos os outros espaços em branco obedecem: é possível tokenizar com ele. Eles são mais como modificadores. No entanto, ZERO WIDTH SPACE
, WORD JOINER
, e ZERO WIDTH NON-BREAKING SPACE
(se usado como diferente de uma marca de ordem de byte) se ajustar à regra de espaço em branco em meu livro. Portanto, eu os incluo na minha classe de caracteres de espaço em branco horizontal.
Em Java:
static public final String HORIZONTAL_WHITESPACE = "[\\p{Blank}\\u200B\\u2060\\uFFEF]"
perl
etiqueta na pergunta original.
[\p{Blank}\u200b\u180e]
são necessários. É certo que faz sentido que um separador de vogal não seja considerado um caractere de espaço em branco, mas por que o espaço de largura zero não está em classes como \s
e \p{Blank}
, me bate.
m/ /g
apenas ceda espaço / /
e funcionará. Ou use \S
- ele substituirá todos os caracteres especiais, como tabulação, novas linhas, espaços e assim por diante.
[\r\f]
.