BTW, esses personagens também são "espaços em branco": [\r\f].
Eugene Yarmash
2
@eugeney alguém ainda está fazendo feeds de formulário? (\ f's)
Aran Mulholland
1
@AranMulholland: qualquer pessoa que possua uma impressora orientada a caracteres. A maioria das impressoras possui um modo de caractere, assim como PostScript ou qualquer que seja a interface da Hewlett Packard, e para lançar uma página, você envia um feed de formulário.
Borodin
1
A @Borodin Hewlett Packard é chamada PCL (Printer Control Language).
CB_Ron
Respostas:
182
As versões 5.10 e posteriores do Perl suportam classes de caracteres verticais e horizontais subsidiárias \ve \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 \ve dezoito caracteres horizontais que correspondem \h. \scorresponde 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 \htambém correspondem a U + 00A0 NO-BREAK ESPAÇO e \vtambém correspondem a U + 0085 NEXT LINE, nenhum dos quais corresponde a\s
@AvinashRaj: Esta pergunta é sobre Perl, que certamente suporta PCRE
Borodin
2
@AvinashRaj: Exceto que [[:blank:]]não corresponde ao espaço sem interrupção - ou"\xA0"
Borodin
6
Quero mencionar que \hfuncionou 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.
squidbe
8
O que torna o Perl um \hpouco fora do padrão é sua inclusão MONGOLIAN VOWEL SEPARATOR. Unicode não considera espaço em branco. Por esse motivo, o Perl \hdifere do POSIX blank( [[:blank:]]no Perl, \p{Blank}no Java) e do Java 8 \h. É certo que é um caso de ponta.
Aleksandr Dubinsky
362
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 \re \nno padrão manipula corretamente todas as convenções de nova linha do Unix (LF), Mac OS (CR) clássico e DOS-ish (CR LF) .
Antes do Perl v5.18, \snão correspondia à guia vertical. [^\S\cK](obscuramente) corresponde ao que \stradicionalmente 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 /aopção estiver em vigor, " \scorresponde [\t\n\f\r ]e, a partir do Perl v5.18, a guia vertical \cK". Descarte \re \ndeixe 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
EOTablemy $class;while(/^0x([0-9a-f]{4})\s+([A-Z\s]+)/mg){my($hex,$name)=($1,$2);nextif $name =~/\b(?:CR|NL|NEL|SEPARATOR)\b/;
$class .="\\N{U+$hex}";}
qr/[$class]/u;}
Outras aplicações
O truque de negativo duplo também é útil para combinar caracteres alfabéticos também. Lembre-se de que \wcorresponde 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
Inteligente, mas o comportamento é muito surpreendente, e não vejo como é menos estranho.
Qwertie
7
@ Qwertie: o que é surpreendente? Menos estranho do que o que?
ysth 12/08/10
9
Excelentemente horrível.
9
Isso é muito bom. Conforme solicitado, você corresponde ao espaço em branco (não apenas a alguns caracteres em branco) e exclui o caractere de avanço de linha. Sua solução não se preocupa com a pergunta: "que caracteres de espaço em branco existem", como não deveria. Era exatamente isso que eu estava procurando. (Como observado por @Rory, uma 'nova linha' também pode incluir \r, por exemplo, no Windows, por isso considero exluding aqueles do jogo, bem como: /[^\S\r\n]/)
Timo
1
Isso certamente atenderá às necessidades do OP e praticamente a todos os que pesquisam essa pergunta (de qualquer forma, falantes de inglês). Mas ainda é uma resposta ruim. Simplesmente não há desculpa para usar esta solução quando \hestiver disponível.
Alan Moore
50
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\npara novas linhas e o Mac OS 9 usado \r. Você é improvável encontrar \rsem \nnos dias de hoje, mas se você encontrá-lo, ele não podia nada média, mas uma nova linha. Assim, como \rpode significar uma nova linha, devemos excluí-la também.
+1 solução de Greg acabou corrompendo o meu texto, seu funcionou bem.
Timo Huovinen
Você pode se surpreender com a quantidade de programas que ainda usam "\ r" para fins de linha. Às vezes, levava um tempo para descobrir que meu problema era que o arquivo as usava. Ou que ele usou a codificação de caracteres MacRoman ...
mivk
2
parece que o @Greg primeiro o "errado" o alterou e não deu crédito a você. É por isso que estou votando aqui.
Andre Elrico 31/03
14
O regex abaixo corresponderia a espaços em branco, mas não a um novo caractere de linha.
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 blankclasse 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, \hescolhe 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:
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]"
Você precisa adicionar os sinalizadores de compilação regexp apropriados à compilação Java e estar executando o Java 7 ou posterior. De qualquer forma, a questão não era sobre Java ou PCRE, portanto tudo isso é imaterial.
tchrist
@tchrist Obrigado por apontar isso. Vou atualizar minha resposta. Eu discordo, porém, que minha resposta é irrelevante. O que é imaterial é a perletiqueta na pergunta original.
Aleksandr Dubinsky
1
@AleksandrDubinsky, \ p {Blank} não é suportado em JavaScript, portanto, definitivamente não é "padrão para todos os sabores de regex" -1
Valentin Vasilyev
Mais informativo. Acho perturbador saber que não existe uma classe geral completa e completa de caracteres abreviados de "espaço em branco horizontal" e que horrores como esse [\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 \se \p{Blank}, me bate.
Timo
Acompanhamento: li que ambos são considerados "neutros em relação aos limites", embora isso não explique o porquê .
Timo
-4
m/ /gapenas 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]
.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 UnicodeO padrão de espaço vertical
\v
é menos útil, mas corresponde a esses caracteresExistem 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 caracteresTodos 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
fonte
\h
funciona apenas nos idiomas suportadosPCRE
.[[: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ãoMONGOLIAN VOWEL SEPARATOR
. Unicode não considera espaço em branco. Por esse motivo, o Perl\h
difere do POSIXblank
([[:blank:]]
no Perl,\p{Blank}
no Java) e do Java 8\h
. É certo que é um caso de ponta.Use um negativo duplo:
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:
Resultado:
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ê
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 .
Outras aplicações
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,mas uma classe de caracteres dupla negativa pode respeitar o código do idioma:
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
ou com uma propriedade Unicode, conforme sugerido pelo szbalint
fonte
\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:
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.fonte
O regex abaixo corresponderia a espaços em branco, mas não a um novo caractere de linha.
DEMO
Se você deseja adicionar retorno de carro também, adicione
\r
o|
operador dentro da cabeça negativa.DEMO
Adicione
+
depois do grupo que não captura para corresponder a um ou mais espaços em branco.DEMO
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 ).DEMO
fonte
O que você está procurando é a
blank
classe de caracteres POSIX . No Perl, é referenciado como:em Java (não se esqueça de ativar
UNICODE_CHARACTER_CLASS
):Comparado com o similar
\h
, o POSIXblank
é 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 oMONGOLIAN 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
, eZERO 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:
fonte
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.fonte