English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Explicação detalhada da afirmação zero-width da expressão regular

Afirmação de largura zero da expressão regular:

A afirmação de largura zero é um ponto difícil da expressão regular, então este capítulo se concentra em uma análise do princípio de combinação. A afirmação de largura zero também tem outros nomes, como "olhar ao redor" ou "pesquisa prévia", etc., mas esses não são o foco de nossa atenção.

1. Conceito básico:

A afirmação de largura zero, como o nome sugere, é uma combinação de largura zero, que não salva o conteúdo combinado no resultado da combinação, e o resultado da combinação final é apenas uma posição.
O efeito é adicionar uma condição limitadora à posição especificada, para determinar que os caracteres antes ou após essa posição devem satisfazer a condição limitadora para que a expressão de caractere da expressão regular possa ser combinada com sucesso.
Atenção: Aqui, o que se diz sobre a subexpressão não é apenas a expressão entre os parênteses, mas qualquer unidade de combinação da expressão regular.
javascript suporta apenas a afirmação de largura zero anterior, e a afirmação de largura zero pode ser dividida em afirmação de largura zero anterior positiva e negativa.

Exemplo de código a seguir:

Código de exemplo um:

var str="abZW863";
var reg=/ab(?=[A-Z])/;
console.log(str.match(reg));

No código acima, o significado da expressão regular é: combinar a string "ab" que é seguida por qualquer letra maiúscula. O resultado da combinação final é "ab", porque a afirmação de largura zero "(?=[A-Z])" não combina nenhum caractere, apenas para determinar que a posição seguinte deve ser uma letra maiúscula.

Código de exemplo dois:

var str="abZW863";
var reg=/ab(?![A-Z])/;
console.log(str.match(reg));

No código acima, o significado da expressão regular é: combinar a string "ab" que não é seguida por qualquer letra maiúscula. A expressão regular não combinou nenhum caractere, porque na string, "ab" é seguido por uma letra maiúscula.

II. Princípio de coincidência:

O código acima apenas introduziu o processo de coincidência da afirmação de largura zero de maneira conceitual.
A seguir, apresentaremos respectivamente como a afirmação de largura zero positiva e negativa coincidem de maneira teórica.
1.Afirmação de largura zero positiva:
Exemplo de código a seguir:

var str="<div>antzone";
var reg=/^(?=<)<[^>]+>\w+/;
console.log(str.match(reg));

O processo de coincidência é o seguinte:
Primeiro, o "^" da expressão regular obtém o controle, começa a coincidir a partir da posição 0, coincide com a posição de início 0, coincide com sucesso, e então transferir o controle para o caractere "(?=<)" devido ao "^" ser de largura zero, então "(?=<)" também começa a coincidir a partir da posição 0, ele requer que a posição à direita seja o caractere "<", e a posição 0 é exatamente o caractere "<", coincidir com sucesso, e então transferir o controle para o caractere "<", devido a "(?=<)" também é de largura zero, então ele começa a coincidir a partir da posição 0, então coincidir com sucesso, e não será introduzido o processo de coincidência posterior.

2.Afirmação de largura zero negativa:

Exemplo de código a seguir:

var str="abZW863ab88"; 
var reg=/ab(?![A-Z])/g; 
console.log(str.match(reg));

O processo de coincidência é o seguinte:
Primeiro, o caractere "a" da expressão regular obtém o controle, começa a coincidir a partir da posição 0, coincidir com sucesso com o caractere "a", e então transferir o controle para "b", a partir da posição1A partir da posição tentar coincidir com sucesso com o caractere "b", e então transferir o controle para "(?![A-Z])", ele começa a coincidir a partir da posição2A partir da posição tentar coincidir, ele requer que a posição à direita não possa ser qualquer letra maiúscula, e a posição à direita é a letra maiúscula "Z", falhar na coincidência, e então o controle é devolvido ao caractere "a", e começar a coincidir a partir da posição1A partir da posição tentar, falhar na coincidência, e então o controle é devolvido ao caractere "a", a partir da posição2A partir da posição tentar coincidir, falhar, e tentar repetidamente, até que a partir da posição7A partir da posição tentar coincidir com sucesso, e então transferir o controle para "b", e então começar a coincidir a partir da posição8A partir da posição tentar coincidir com sucesso, e então transferir o controle para "(?![A-Z])", ele começa a coincidir a partir da posição9A partir da posição tentar coincidir, ele determina que a posição à direita não pode ser uma letra maiúscula, coincidir com sucesso, mas ele não coincidirá realmente com o caractere, então o resultado da coincidência final é "ab".

A seguir, vamos complementar

A afirmação de largura zero é um método da expressão regular, a expressão regular na ciência da computação é uma string usada para descrever ou coincidir uma série de strings que atendem a certas regras sintáticas.

Definição e explicação

A afirmação de largura zero é um método da expressão regular
A expressão regular na ciência da computação é uma string usada para descrever ou coincidir uma série de strings que atendem a certas regras sintáticas. Em muitos editores de texto ou outras ferramentas, a expressão regular geralmente é usada para pesquisar e/ou substituir o conteúdo de texto que coincide com um padrão específico. Muitos linguagens de programação suportam operações de string usando expressões regulares. Por exemplo, no Perl, há um motor de expressão regular poderoso integrado. O conceito de expressão regular foi popularizado pelos utilitários de ferramentas do Unix (por exemplo, sed e grep). A expressão regular geralmente é abreviada como 'regex', no singular regexp, regex, e no plural regexps, regexes, regexen.

Afirmações de largura zero

Usado para encontrar algo antes ou depois de um conteúdo específico (mas não incluindo esses conteúdos), ou seja, eles são como '\b', '^', '$', que especificam uma posição que deve atender a certas condições (ou seja, a afirmação), portanto, também são chamados de afirmações de largura zero. Melhor usar exemplos para explicar: As afirmações são usadas para declarar uma verdade que deve ser verdadeira. A expressão regular continua a coincidir apenas quando a afirmação for verdadeira.

(?=exp) também é chamado de avanço positivo de largura zero, que afirma que a posição subsequente pode coincidir com a expressão exp. Por exemplo, '\b(?=re)\w+\b, coincidirá com a parte posterior da palavra que começa com 're' (exceto 're'), por exemplo, ao procurar 'reading a book.', ele coincidirá com 'ading'.

var reg = new Regex(@"\w+(?=ing)");
var str = "muing";
Console.WriteLine(reg.Match(str).Value);//Retorna mu

(?<=exp) também é chamado de retrovisão positiva de largura zero, que afirma que a posição anterior pode coincidir com a expressão exp. Por exemplo, '\b\w+(?<=ing\b) coincidirá com a parte anterior da palavra que termina com 'ing' (exceto 'ing'), por exemplo, ao procurar 'I am reading.', ele coincidirá com 'read'.

Se você quiser adicionar uma vírgula a cada três dígitos de um número longo (claro, começando pela direita), você pode buscar a parte que precisa de vírgulas antes e dentro dela: ((?=\d)\d{3}+\b, usá-lo para1234567890 ao buscar o resultado é234567890。
O exemplo a seguir usa这两种断言:(?<=\s)\d+(?=\s) coincide com o número separado por espaços em branco (reitero, não inclui esses espaços em branco).

Negação de largura zero

Anteriormente, mencionamos como encontrar um caractere que não é um caractere específico ou não está em um conjunto de caracteres específico (oposto). Mas e se quisermos garantir que um caractere não apareça, mas não quisermos coincidir com ele? Por exemplo, se quisermos encontrar palavras como--Dentro dela, há a letra 'q', mas a letra 'q' não é seguida por uma letra 'u', podemos tentar assim:

\b\w*q[^u]\w*\b coincidirá com a palavra que contém um 'q' seguido por um caractere que não é 'u'. Mas se fizer mais testes (ou se sua mente for suficientemente aguda, você pode observá-lo diretamente), perceberá que, se o 'q' aparecer no final da palavra, como em 'Iraq', 'Benq', essa expressão estará errada. Isso ocorre porque [^u] sempre coincide com um caractere, então se o 'q' for o último caractere da palavra, o [^u] coincidirá com o delimitador de palavra subsequente (pode ser um espaço, um ponto ou outro), e o '\w*\b coincidirá com a próxima palavra, então '\b\w*q[^u]\w*Pode coincidir com o termo inteiro 'Iraq fighting'. A negação de largura zero pode resolver esse problema, pois coincide apenas com uma posição, sem consumir nenhum caractere. Agora, podemos resolver o problema dessa forma: '\b\w*q(?!u)\w*\b).

Zero-width negative predictive lookahead assertion (?!exp) para afirmar que a posição posterior não pode coincidir com a expressão exp. Por exemplo: \d{3})(?!\d) coincide com três dígitos e esses três dígitos não podem ser seguidos por números;\b((?!abc)\w)+\b para coincidir com uma palavra que não contém a sequência de caracteres contínuos 'abc'.
Da mesma forma, podemos usar (?<!exp), zero-width negative lookahead assertion para afirmar que a posição anterior não pode coincidir com a expressão exp: (?<![a-z])\d{7} coincide com um número de sete dígitos que não começa com uma letra minúscula.

Um exemplo mais complexo: (?<=<(\w+)>).*(?=<\/\1>) coincide com o conteúdo dentro de uma etiqueta HTML simples sem atributos. (<?=(\w+)>) especifica tal prefixo: uma palavra entre colchetes pontiagudos (por exemplo, pode ser <b>), seguido de .*(qualquer string), seguido por um sufixo (?=<\/\1>). Atente para o \/,que usa a caracteres escapados mencionados anteriormente;\1é uma referência inversa, que faz referência ao primeiro grupo capturado, antes do (\w+) do conteúdo coincidente, assim se o prefixo for realmente <b>, o sufixo será </b> e <. A expressão completa coincide com <b> e </b> entre o conteúdo (novo lembrete, não inclui o prefixo e sufixo).

Agora, um pouco cansativo de ver acima. Vamos adicionar algumas informações adicionais:

As assegurações são usadas para declarar uma verdade que deve ser verdadeira. A expressão regular continuará a coincidir apenas quando a asseguração for verdadeira.
Os próximos quatro são usados para procurar algo antes ou depois de determinado conteúdo (mas não incluem esses conteúdos), ou seja, eles são usados como \b, ^, $ para especificar uma posição que deve atender a certas condições (ou seja, assegurações), portanto, também são chamadas de assertions de zero-width. Melhor ainda, vamos usar exemplos para explicar:

(?=exp) também chamada de zero-width positive lookbehind assertion, ela afirma que a posição posterior pode coincidir com a expressão exp. Por exemplo \b\w+(?=ing\b),coincide com a parte anterior de uma palavra que termina com 'ing' (exceto 'ing'), por exemplo, ao procurar 'I'm singing while you're dancing.', ela coincide com 'sing' e 'danc'.
(?<=exp) também chamada de zero-width positive lookahead assertion, ela afirma que a posição anterior pode coincidir com a expressão exp. Por exemplo (?<=\bre)\w+A expressão de regularidade coincide com a parte posterior de uma palavra que começa com 're' (exceto 're'), por exemplo, ao procurar 'reading a book', ela coincide com 'ading'.

Se você quiser adicionar uma vírgula a cada três dígitos de um número longo (claro, começando pela direita), você pode buscar a parte que precisa de vírgulas antes e dentro dela: ((?<=\d)\d{3}*\b, usá-lo para1234567890 ao buscar o resultado é234567890。
O exemplo a seguir usa这两种断言:(?<=\s)\d+(?=\s) coincide com o número separado por espaços em branco (reitero, não inclui esses espaços em branco).

Suplemento dois:

Recentemente, para processar o código-fonte do arquivo html, foi necessário realizar uma busca e substituição regular. Então, aproveitando essa oportunidade, aprendi sistematicamente sobre expressões regulares, embora já tivesse usado expressões regulares antes, sempre aprendendo de maneira temporária para passar. Durante o processo de aprendizado, ainda encontrei muitos problemas, especialmente a predição avançada zero-width (aqui ainda vou reclamar, em todos os lugares na internet há muita cópia e cola, ao encontrar um problema, vi muitos conteúdos repetidos, suor!!!), então aqui escrevi minha compreensão para facilitar a consulta futura!

      O que é uma predição avançada zero-width? Veja a definição oficial na MSDN

(?= expressão)

(零宽度正预测先行断言。)A correspondência continua apenas quando a sub-expressão coincide na posição à direita desta. Por exemplo, \w+(?=\d) coincide com a palavra que segue o número, mas não com o número.

      Exemplo clássico: um palavra termina com ing, queremos obter o conteúdo antes de ing

var reg = new Regex(@"\w+(?=ing)");
var str = "muing";
Console.WriteLine(reg.Match(str).Value);//Retorna mu

      Os exemplos acima são vistos em todos os lugares na internet, até aqui talvez você tenha compreendido que, originalmente, retornou o conteúdo antes da expressão exp.

     Vamos ver o código abaixo

var reg = new Regex(@"a(?=b)c");
var str = "abc";
Console.WriteLine(reg.IsMatch(str));//Retorna falso

      Por que retorna falso?

     Na verdade, a definição oficial da MSDN já disse isso, só que foi dito de maneira oficial. Aqui precisamos prestar atenção a um ponto crucial: essa posição. Não, é posição, não caractere. Então, combinando com a definição oficial e o primeiro exemplo para entender o segundo exemplo:

     Como a seguir é b, então retornamos o conteúdo de correspondência a (sabemos pelo primeiro exemplo que só retornamos a, não o conteúdo de correspondência exp), então a(?=b)c63A parte b) já foi resolvida, agora precisamos resolver o problema de correspondência de c. Neste momento, a correspondência de c deve começar onde? Combinando com a definição oficial, sabemos que deve começar da posição do sub-expressão para a direita, então é a partir da posição b, mas b não corresponde a a(?=b)c restante c, então abc não combina com a(?=b)c foi.

     Então, se queremos fazer a correspondência acima, como escreveremos a expressão regular?

     A resposta é: a(?=b)bc

     Claro, alguém pode dizer que diretamente abc já se encaixa, por que precisamos de tanto esforço? Claro que não precisamos, apenas para explicar como é a zero-width positive lookahead assertion. Sobre outros zero-width assertions também são do mesmo princípio!

Adição três

(?=exp): zero-width positive lookahead assertion, asserting that the position after can match the expression exp.

#matches after _path, result is product
  'product_path'.scan /(product)(?=_path)/

(?<=exp): zero-width positive lookbehind assertion, asserting that the position before can match the expression exp

#matches before name:, result is wangfei
'name:wangfei'.scan /(?<=name:)(wangfei)/ #wangfei

(?!exp): zero-width negative lookahead assertion, asserting that the position after cannot match the expression exp.

#matches after not _path
'product_path'.scan /(product)(?!_path)/  #nil
#matches after not _url
'product_path'.scan /(product)(?!_url)/  #product

(?<!exp): zero-width negative lookbehind assertion to assert that the position before cannot match the expression exp

#matches before not name:
'name:angelica'.scan /(?<!name:)(angelica)/  #nil
#matches before not nick_name:
'name:angelica'.scan /(?<!nick_name:)(angelica)/#angelica

O editor também está cansado dessa coisa, espera-se que tenha algo bom para compartilhar, vá para a cama hoje

Você também pode gostar