usando expressão quantificador regex simples no grep

1

Alguém sabe por que ls | xargs -n 1 basename | grep -E '[0-9]{1}' não mostra apenas ocorrências de um único dígito entre 0-9?

Por exemplo, se eu tiver:

touch 1
touch 22
touch 333
touch test_file

Se eu executar ls | xargs -n 1 basename | grep -P '[0-9]{1}' :

Eu recebo 1, 22 e 333 arquivos listados.

Se eu executar ls | xargs -n 1 basename | grep -P '[0-9]{2}' :

Eu recebo 22 e 333 arquivos listados.

Espero que o {2} mostre apenas o arquivo 22.

    
por Flo Woo 24.07.2013 / 07:02

4 respostas

4

Eu acho que a razão pela qual você está esperando algo diferente do que está acontecendo é que você está tomando

[0-9]{n}

significa coincidir exatamente com n ocorrências de caracteres em [0-9] e descartar o resto, quando o que ele faz é encontrar n ocorrências de caracteres em [0-9] e chamá-lo de correspondência. Então, em

[0-9]{1}

ele encontra exatamente uma ocorrência de algo correspondente a [0-9], de modo que 1 corresponde a uma, em seguida, ao examinar a 22, ela para nas duas primeiras e considera uma correspondência sem olhar para o resto. Similarmente para o 333. Se você especificou

[0-9]{2}

não corresponderia a 1, mas a 22 correspondências e, em seguida, a 33 em 333 combinações.

Como disse o slm, limites de palavras são a passagem aqui. Você tem tanto o -P quanto o -E flavors do grep regex correspondentes em sua pergunta. Você pode usar o GNU \ < e \ > com -E assim:

ls | xargs -n 1 basename | grep -E '\<[0-9]{1}\>'

ou o \ b com o -E ou o pcre correspondente -P como este

ls | xargs -n 1 basename | grep -P '\b[0-9]{1}\b'
    
por 24.07.2013 / 07:59
3

Use grep -x para encontrar correspondências exatas, em vez de encontrar correspondências dentro das linhas.

grep foo encontra linhas que contêm foo , enquanto grep -x foo encontra linhas que são foo .

A mesma coisa, grep -E '[0-9]{1}' (igual a grep '[0-9]' ) encontra linhas que contêm um dígito. grep -xE '[0-9]{1}' encontra linhas que consistem em um dígito.

Com o GNU grep , você pode usar as opções --color ou -o para ver o que está sendo correspondido, embora mostre todas as correspondências.

    
por 24.07.2013 / 08:24
1

Isso ocorre porque os dois primeiros caracteres de 333 correspondem à regex, portanto, toda a linha corresponde.

Se você quiser evitar, use:

(^|[^0-9])[0-9]{2}([^0-9]|$)
    
por 24.07.2013 / 07:26
0

Se você colocar o conteúdo dos seus exemplos em um arquivo de texto, poderá ver por que grep está correspondendo a ele:

$ grep -E '[0-9]{1}' file.txt
touch 1
touch 22
touch 333

Você pode usar limites de palavras ( -w ) para informar a grep que deseja corresponder apenas uma única palavra do seu regex ( \<REGEX\> ) em vez de qualquer string que corresponda a ela:

$ grep -Ew '\<[0-9]{1}\>' file.txt
touch 1

$ grep -Ew '\<[0-9]{2}\>' file.txt
touch 22

$ grep -Ew '\<[0-9]{3}\>' file.txt
touch 333

O \< e \> informam grep onde estão os limites. Isso força grep a corresponder a palavras explícitas, como 1, mas não a strings como 11, 111 ou aa11aa, pois a regex dessas strings não está contida por limites de palavras.

    
por 24.07.2013 / 07:39