awk: erro: tenda de \ {\}

3

Eu uso o seguinte regex para encontrar endereços de e-mail:

echo "[email protected]" | awk '/^([a-zA-Z0-9_-.\+]+)@([a-zA-Z0-9_-.]+).([a-zA-Z]{2,5})$/ {print $0}'

Mas retorna o erro:

 awk: cmd. line:1: error : tent of \{\}
    
por sci9 06.06.2018 / 11:53

4 respostas

2

Versão curta, use isto:

$ echo "[email protected]" | 
>    gawk '/^([-a-zA-Z0-9_.+]+)@([-a-zA-Z0-9_.]+)\.([a-zA-Z]{2,5})$/'

Supondo que a mensagem de erro real é algo como:

awk: cmd. line:1: error: Invalid range end: …

Em seguida, há quatro problemas na sua linha:

  1. O traço ( - ) significa "intervalo de caracteres", não um traço explícito.

    O motivo da mensagem de erro é que os dois caracteres ao redor do traço ( - ) dentro do intervalo de caracteres ( _ e . ) não estão na ordem (ASCII). O intervalo de caracteres .-_ não gera erros. Mas tenho certeza de que você não pretende dizer "intervalo de caracteres" (todos os caracteres entre um ponto . e um sublinhado _ ), mas para corresponder a um traço explícito ( - ).

    Para corresponder a um traço explícito dentro de uma "expressão de colchetes", é necessário torná-lo o primeiro ou o último caractere do intervalo. [-…] , […-] . Ou, desanimado, escape \- . Ou seja, ambos os trabalhos:

    [-a-zA-Z0-9_.+]
     [a-zA-Z0-9_.+-]
    

    Mas não, uma barra invertida é não uma solução geral para tornar um traço explícito. Experimente:

    $ echo 'ab-cd' | grep -Eo '[a\-c]+'
    ab
    c
    

    O regex do grep (mesmo se estendido: -E ) não corresponde ao traço.

  2. O + não é especial dentro de uma "expressão de colchetes", portanto, ele não precisa de escape (e escapar dentro de "expressões de colchetes" é um mau hábito). Use isto:

    ^([-a-zA-Z0-9_.+]+)@
    
  3. Um ponto . é um caractere especial que "corresponde a qualquer caractere, exceto a nova linha".
    Como tal, você precisa fugir dele \. ou usar uma "expressão de colchetes" [.] para corresponder explicitamente a um caractere de ponto, use este:

    ^([-a-zA-Z0-9_.+]+)@([-a-zA-Z0-9_.]+)\.
    
  4. E, finalmente, a "expressão de intervalo" é uma extensão sobre implementações históricas do awk, pode não funcionar em todos os awk's. Isso geralmente não é "um problema", mas se for, você precisará usar:

    ([a-zA-Z][a-zA-Z][a-zA-Z]?[a-zA-Z]?[a-zA-Z]?)$
    

Mas você provavelmente está usando o GNU awk, e a sintaxe correta deve ser:

$ echo "[email protected]" | 
>    gawk '/^([-a-zA-Z0-9_.+]+)@([-a-zA-Z0-9_.]+)\.([a-zA-Z]{2,5})$/'
    
por 06.06.2018 / 22:56
2

Resposta:

echo "[email protected]" | awk '/^([-a-zA-Z0-9_.\+]+)@([-a-zA-Z0-9_.]+).([a-zA-Z]{2,5})$/ {print $0}'
[email protected]

Explicação: O caractere - é ambíguo na posição em que você o coloca, pois pode representar um intervalo. Movê-lo para o início do regexp ou para escapar, funciona bem.

Mais informações: Verifique suas regexes neste site útil em caso de dúvida.

Como corretamente apontado por Isaac , o último ponto na expressão não faz o que você provavelmente acha faz: . representa qualquer caractere, e você deve escapar dele se você quiser que signifique um ponto literal \.

Outras otimizações incluem o não escape de caracteres dentro de colchetes, já que é desnecessário. Estou apontando para \+ no primeiro conjunto de caracteres, e tenho que agradecer Isaac novamente por descobrir isso !

Mais uma coisa que está além de mim é por que você usaria todos esses parênteses () .

Além de corrigir o uso de - e sugerir algumas pequenas melhorias, o tema subjacente é a oportunidade amplamente discutida de empregar expressões regulares para validar endereços de e-mail. A correspondência correta de qualquer endereço de e-mail é uma tarefa difícil que requer uma expressão muito mais complexa do que se imaginaria inicialmente. Uma opinião razoável, geralmente encontrada em fóruns semelhantes, é usar o regex mais simples que, com certeza, irá funcionar com o conjunto de dados.

    
por 06.06.2018 / 12:18
1

O hífen - é um caractere especial na classe de caracteres ( Expressão de colchetes ) qual especificando o intervalo de caracteres. Se você quiser adicionar o literal - em sua classe de caracteres, você precisará escapar ou movê-lo para o final ou início (após o ^ , se houver) da sua classe de personagem.

[a-z-]
[-a-z]
[a-z\-A-Z]

7.[...]

The < hyphen-minus > character shall be treated as itself if it occurs first (after an initial ^, if any) or last in the list, or as an ending range point in a range expression. As examples, the expressions [-ac] and [ac-] are equivalent and match any of the characters 'a', 'c', or '-'; [^-ac] and [^ac-] are equivalent and match any characters except 'a', 'c', or '-'; [...]

If a bracket expression specifies both '-' and ']', the ']' shall be placed first (after the '^', if any) and the '-' last within the bracket expression.

    
por 06.06.2018 / 12:34
0

Qual versão de awk você está usando?

Este comando não erra quando eu uso o GNU awk , embora não produza saída.

Usando solaris awk , esse erro é produzido:

awk: syntax error near line 1
awk: bailing out near line 1

Ao ler seu regex , ele nunca corresponderá a um endereço de e-mail ...

    
por 06.06.2018 / 11:59