Acabei de encontrar um bug awk?

0

Usando test2.txt

$ cat /tmp/test2.txt | hexdump -C
00000000  47 61 6c 6c 6f 20 63 65  6c 74 69 63 6f 0a 47 65  |Gallo celtico.Ge|
00000010  73 97 20 42 61 6d 62 69  6e 6f 0a                 |s. Bambino.|

Aqui está o que aconteceu com awk :

$ cat /tmp/test2.txt | awk '/\x97/{print}'
Ges Bambino

$ cat /tmp/test2.txt | awk '/[\x7F-\xFF]/{next;}; 1'
Gallo celtico
Ges Bambino

Ou seja, a linha Ges Bambino line contém um caractere \x97 e awk confirma isso no primeiro comando. No entanto, \x97 está no intervalo de \x7F-\xFF , portanto, a linha deve ser ignorada no segundo comando, mas não foi.

Isso realmente parece um erro awk para mim.
Algum comentário?

PS. tornando mais evidente:

$ cat /tmp/test2.txt | awk '/\x97/{next}; 1'
Gallo celtico

$ cat /tmp/test2.txt | awk '/[\x97]/{next}; 1'
Gallo celtico
Ges Bambino

ATUALIZAÇÃO:

Como @KamilMaciorowski apontou, é relacionado localmente. Ou seja o acima acontece quando sob

$ set | egrep '^LANG|^LC'
LANG=zh_CN.UTF-8

considerando que ambos

cat /tmp/test2.txt | LC_ALL=C awk '/[\x97]/{next}; 1'
cat /tmp/test2.txt | LC_ALL=C awk '/[\x7F-\xFF]/{next;}; 1'

estão dando resultados corretos.

Ainda assim, isso é um problema, é?

    
por xpt 22.07.2017 / 17:32

1 resposta

2

Bytes e caracteres são idênticos apenas na localidade C (aka POSIX ) padrão, mas em todas as outras localidades eles são diferentes. Portanto, se o seu sistema usa uma localidade UTF-8 (por exemplo, en_US.UTF-8 ) por padrão, então as "classes de caractere" entre parênteses em gexk regexes são baseadas em caracteres , não em bytes individuais.

Por exemplo, /[eęė]/ é equivalente a /[e\xC4\x99\xC4\x97]/ , assumindo uma localidade * .UTF-8; no entanto, ele corresponderá à letra ę , mas não č , apesar de ambos terem C4 byte. (Por alguma razão, isso é diferente de uma simples /\xC4/ fora de uma classe de caracteres, que faz corresponder ao byte literal C4 .)

De qualquer forma, o mesmo se aplica a intervalos dentro de classes de caracteres e, como o byte FF não cria uma sequência UTF-8 válida, a biblioteca regex pode declarar inválido todo o intervalo ou algo assim.

O gawk tem a opção -b , --characters-as-bytes para desativar isso.

    
por 22.07.2017 / 18:16

Tags