Diferença entre '.' , '?' e '*' em expressões regulares?

21

Eu poderia obter um exemplo de como esses três elementos (são chamados de metacaracteres?) Diferem?

Sei que isso *significa tudo ou nada, mas não tenho certeza se é a maneira certa de pensar sobre isso. Por outro lado, .e ?parece o mesmo. Eles combinam com um personagem, certo?

posixKing
fonte
@Cyrus ou melhor ainda: a documentação StackOverflow Regex .
Thomas Ayoub

Respostas:

16

Retirado direto da Wikipedia :

? O ponto de interrogação indica zero ou uma ocorrência do elemento anterior. Por exemplo, colou? R corresponde a "cor" e "cor".

*O asterisco indica zero ou mais ocorrências do elemento anterior. Por exemplo, ab * c corresponde a "ac", "abc", "abbc", "abbbc" e assim por diante.

A grande diferença é que o asterisco corresponde a zero ou mais ocorrências, enquanto o ponto de interrogação corresponde a zero ou uma ocorrência. Compare estes dois exemplos:

$ printf "colour\ncolor\ncolouur\n" | egrep 'colou?r'                          
colour
color
$ printf "colour\ncolor\ncolouur\n" | egrep 'colou*r'                          
colour
color
colouur

Como na colouurletra u (o elemento anterior antes do qualificador ?) ocorreu mais de uma vez, ela não corresponde ?, mas corresponde a*

Exemplo semelhante:

$ printf "error\neror\ner\n" | egrep 'er?or'                                   
eror
$ printf "error\neror\ner\n" | egrep 'er*or'                                   
error
eror

Na mesma página da Wikipedia:

Corresponde a qualquer caractere único (muitos aplicativos excluem novas linhas, e exatamente quais caracteres são considerados novas são de sabor, codificação de caracteres e específicos da plataforma, mas é seguro supor que o caractere de avanço de linha esteja incluído). Nas expressões de colchete POSIX, o caractere de ponto corresponde a um ponto literal. Por exemplo, ac corresponde a "abc" etc., mas [ac] corresponde apenas a "a", "." Ou "c".

No nosso exemplo,

$ printf "colour\ncolor\ncolouur\n" | egrep 'colo.r'                           
colour
$ printf "colour\ncolor\ncolouur\n" | egrep 'colou.r'                          
colouur

Apropriadamente, o último lê como match any line that has "colou", plus any character, plus letter "r"

Conclusão

Você perguntou: "Eu sei que '*' significa tudo ou nada, mas não tenho certeza se é a maneira certa de pensar sobre isso. Por outro '.' & '?' parece o mesmo. " Como você pode ver, o ponto e o asterisco não são exatamente iguais. O ponto opera com qualquer caractere que possa estar ocupando essa posição específica, enquanto o ponto de interrogação opera no elemento anterior.

Sergiy Kolodyazhnyy
fonte
32

Você pode estar confundindo expressões regulares com globs de shell

Na expressão regular, a sintaxe .representa qualquer caractere único (geralmente excluindo o caractere de nova linha), enquanto *é um quantificador que significa zero ou mais do átomo de regex anterior (caractere ou grupo). ?é um quantificador que significa zero ou uma instância do átomo anterior ou (nas variantes de expressões regulares que o suportam) um modificador que define o comportamento do quantificador como não ganancioso.

Em globs de shell, ?representa um único caractere (como o do regex .) enquanto *representa uma sequência de zero ou mais caracteres (equivalente ao regex .*).

Algumas referências que você pode achar úteis são: http://www.regular-expressions.info/quickstart.html e http://mywiki.wooledge.org/glob

chave de aço
fonte
6

Nota: Examples provided are in Python.Embora o conceito permaneça o mesmo.

'.'é um símbolo correspondente que corresponde a qualquer caractere, exceto o caractere de nova linha (isso também pode ser substituído pelo re.DOTALLargumento em Python). Por isso, também é chamado como curinga .

'*'é um quantificador (define com que frequência um elemento pode ocorrer). É a abreviação de {0,} .

Significa "igualar zero ou mais" - o grupo que precede a estrela pode ocorrer várias vezes no texto. Pode estar completamente ausente ou repetido várias vezes.

'?'também é um quantificador . É a abreviação de {0,1} .

Significa "Corresponder a zero ou a um grupo que precede esse ponto de interrogação". Também pode ser interpretado como a parte que precede o ponto de interrogação é opcional .

por exemplo:

pattern = re.compile(r'(\d{2}-)?\d{10}')
mobile1 = pattern.search('My number is 91-9999988888')
mobile1.group()
Output: '91-9999988888'

mobile2 = pattern.search('My number is 9999988888')
mobile2.group()
Output: '9999988888'

No exemplo acima '?' indica que os dois dígitos anteriores a ele são opcionais. Eles podem não ocorrer ou ocorrer no máximo uma vez.

Diferença entre '.' e '?':

'.'corresponde / aceita / verifica qualquer caractere único para o lugar que está mantendo na expressão regular.

por exemplo:

pattern = re.compile(r'.ot')
pattern.findall('dot will identify both hot and got.')
Output: ['dot', 'hot', 'got']

'?'corresponde / verifica a ocorrência zero ou única do grupo que a precede .

Veja o exemplo de número de celular.

O mesmo acontece com '*'. Ele verificará zero ou mais ocorrências do grupo que a precede .

Combinação:

'.*': Aceita quantas sequências estiverem disponíveis. Abordagem gananciosa .

'.*?Aceita a primeira sequência correspondente e para. Abordagem não gananciosa

Para obter mais informações, considere a leitura após duas perguntas ...

Dhaval Simaria
fonte