Por que esta regex encontra uma correspondência para \ x63 com um padrão [\ 80- \ BF]?

0

Estou tentando filtrar bytes UTF-8 válidos / inválidos, mas obtenho resultados estranhos da regex a seguir (destinada a manipular um formato de 3 bytes de UTF-8).

Eu pretendia que o padrão não não correspondesse aos bytes de teste '\xE0\xA1\x63' , mas sim ...
o que estou perdendo?

showmatch() {
  echo -ne "    --> "
  echo -ne "$bytes" | 
    # strip whitespace from the pattern
    perl -l -ne '/^'${1// /}'$/x and print' |
      tr -d '\n' |
        xxd -p |
          tr -d '\n'
  echo; 
}

bytes='\xE0\xA1\x63'
echo -n "before: "; echo -ne "$bytes" |xxd -p
# Note: all whitespace is stripped from each regex pattern.
#           Bytes 1 and 2 and 3
#          (---------------------------------------------------------------------------------------------------)
#              Bytes 1 and 2
#             (------------------------------------------------------------------------------)                  
#                [byt1][byt2-----]  |  [byt1][byt2-----]  |  [byte-1------------][byt2-----]      [byt3----]                                                          
#                =================     =================     ===============================      ==========                            
showmatch '(  ( ([\xE0][\xA0-\xBF]) | ([\xED][\x80-\x9F]) | ([\xE1-\xEC\xEE-\xEF][\x80-\xBF]) )  ([-\xBF])  )'
#
# witout spaces:
showmatch '((([\xE0][\xA0-\xBF])|([\xED][\x80-\x9F])|([\xE1-\xEC\xEE-\xEF][\x80-\xBF]))([-\xBF]))'
#
exit

Aqui está a saída

before: e0a163
    --> e0a163
    --> e0a163
    
por Peter.O 04.05.2011 / 20:36

2 respostas

4

Parece que você esqueceu um x na última parte do regex:

[-\xBF]  -->  [\x80-\xBF]
    
por 04.05.2011 / 20:47
2

Você viu o erro, bom. O que seria útil agora é descobrir erros semelhantes ou evitá-los no futuro.

Você já atingiu o modificador x do Perl para os operadores regexp, o que permite que você tenha espaço em branco nos regexps. Sua construção correspondente seria escrita com novas linhas (o que permitiria que você adicionasse comentários).

/(  ( ([\xE0][\xA0-\xBF]) |
      ([\xED][\x80-\x9F]) |
      ([\xE1-\xEC\xEE-\xEF][\x80-\xBF]) )
    ([-\xBF])  )/x

ou sem os parênteses que não são necessários aqui:

/([\xE0][\xA0-\xBF]|
  [\xED][\x80-\x9F]|
  [\xE1-\xEC\xEE-\xEF][\x80-\xBF])
 [-\xBF] /x

Eu acho que a falta de x se destaca mais desse jeito.

    
por 04.05.2011 / 23:36