Sed e captura de grupos lutam

1

Eu tenho um arquivo de texto com esta aparência

(111)1111111
(111)-111-1111
(111)111-1111
111.111.1111

que estou usando para praticar captura de grupo com regex e sed. O comando que estou executando no arquivo (chamado test) é

sed 's/(?\(\d(3}\)[-.]?\(\d{3}\)[-.]?\(\d{4}\)/' test > output

Esperando a saída que é apenas todos os 1s em todas as linhas. No entanto, o que estou recebendo é apenas o arquivo inteiro sem alterações. O que está errado?

    
por RhythmInk 25.04.2018 / 01:15

3 respostas

6

Na regex básica padrão, (?\(\d(3}\)[-.]? significa:

a literal left parenthesis
a literal question mark
(start of a group)
a literal character 'd'
a literal left parenthesis 
the number '3'
a literal closing brace
(end of group)
a dash or a dot
a question mark

, isto é, imprimirá x :

echo '(?d(3}-?' |sed 's/(?\(\d(3}\)[-.]?/x/'

É muito provável que você queira que sed -E ative as expressões regulares estendidas (ERE) e, em seguida, use ( e ) para agrupamento e \( e \) para parênteses literais.

Observe também que \d é parte de regexes Perl, não de padrão, e enquanto o GNU sed suporta alguns \X escapes, eles não são padrão (e eu não acho que ele suporta \d ). Mesmo para \? , o GNU sed suporta no BRE para significar o que ? significa em ERE, mas não é padrão.

Com tudo isso em mente:

$ echo '(123)-456-7890' | sed -E 's/\(?([0-9]{3})\)?[-.]?([0-9]{3})[-.]?([0-9]{4})//'
1234567890

Embora você possa quase apenas forçar a força bruta e remover tudo, menos os dígitos:

$ echo '(123)-456-7890' | sed -e 's/[^0-9]//g'
1234567890

(isso também aceitaria coisas como (123)-4.5-6-7a8b9c0 ...)

Veja também:

por 25.04.2018 / 01:30
0

Podemos fazer isso abaixo do comando awk também

echo "123-45-6789-10101"| awk '{gsub("[^0-9]","",$1);print }'

Saída

12345678910101
    
por 25.04.2018 / 06:34
0

ilkkachu descrito muito bem por sua expressão regular não funciona com sed (é em um dialeto não suportado).

Aqui está uma maneira alternativa que apenas exclui os caracteres que não são 1 :

sed 's/[^1]//g' file

Para usar grupos, você pode fazer algo como

sed -E 's/([^1]*)(1+)([^1]*)//g' file

Isto é, encontrar uma string não-vazia de uns delimitados em ambos os lados por uma corda possivelmente vazio de não-queridos, e substituir tudo isso com o texto correspondente da queridos.

Altere 1 para [0-9] e [^1] para [^0-9] para processar todos os dígitos.

    
por 25.04.2018 / 08:24