Quais expressões corresponderiam ao padrão (^[0-9]..[a-zA-Z ]+$) no comando grep? festa Linux

Quais expressões corresponderiam ao padrão (^[0-9]..[a-zA-Z ]+$) no comando grep? festa Linux

Estou tentando entender quais expressões exatamente a expressão regular (^[0-9]..[a-zA-Z ]+$)detecta no grepcomando (terminal Linux)

Eu sei que se eu escrevesse o seguinte comando:

grep ^[0-9]..[a-zA-Z] filename.txt

Detectarei qualquer linha que contenha expressões como 92afg Mas não tenho certeza do que +$significa e que tipo de expressões poderei detectar com o comando

grep ^[0-9]..[a-zA-Z]+$ filename.txt

Tentei abrir um novo arquivo de texto e apenas digitar expressões que pensei que seriam detectadas, mas nenhuma delas correspondia, então agradeceria uma explicação sobre isso.

Responder1

Vamos decompô-lo. Primeiro de tudo, observe que este RegExp usa o"Expressão regular estendida"sintaxe (ERE) - +é um metacaractere que não funciona na sintaxe de "Expressão regular básica" grepusada por padrão (o que significa que corresponderia a si mesmo e exigiria um literal +nessa posição), então se você quiser usar esse RegEx com grep, você precisará passar a -Eopção.

  • A ^é uma âncora que liga esta posição da regex ao início da linha.
  • The [0-9]é uma lista de caracteres e corresponderá a qualquer caractere único (1) que se enquadre no intervalo de classificação entre 0e 9. O que exatamente isso inclui depende da "ordem de agrupamento", determinada, entre outros, pela variável de ambiente LC_COLLATE.
  • Corresponde .a qualquer caractere único, então dois ..significa "quaisquer dois caracteres".
  • A [a-zA-Z]parte de trás é uma lista de caracteres e corresponderá aos caracteres (1) que estão entre ae ze também aqueles que estão entre Ae Z. Novamente, o que isso significa depende da ordem de agrupamento!
  • O +significa "um ou mais dos anteriores"
  • A $é uma âncora que liga esta posição da regex ao final da linha.

Então, seu RegExdestina-se a(1) combine quaisquer linhas que

  • comece com qualquer dígito
  • seguido por quaisquer dois caracteres
  • e contém apenas letras (mas pelo menos uma) até o final da linha.

(1) para saber o que realmente pode fazer, veja abaixo

Algumas notas

  1. No seu exemplo, você usa a expressão regular sem aspas. Isso significa que quaisquer caracteres estão abertos à interpretação do shell antes de serem passados ​​para o grepcomando. Se o seu padrão contém $caracteres globbing ( *, ?e [...]listas de caracteres!), o shell pode tentar realizar expansão de variáveis ​​(substituindo assim partes do seu RegEx) ou expandir padrões globbing em possivelmente vários nomes de arquivos, para que no final você tenha mais argumentos na linha de comando que você pretendia originalmente. Outros caracteres especiais do shell ( >, e #semelhantes ;) podem levar a um comportamento ainda mais inesperado. Você deveria usar

    grep -E '^[0-9]..[a-zA-Z]+$' filename.txt
    

    em vez de. Observe que você pode se livrar das âncoras de abertura e fechamento usando o -xsinalizador para impor a correspondência de "linha inteira":

    grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
    
  2. Listas de caracteres contendo intervalos (como a-z) sãoperigosoporque eles podem não lhe dar o que você pensa. Ingenuamente, pode-se esperar que eles correspondam a todos os caracteres que estão entre o caractere inicial e final na tabela ASCII, mas isso só é verdade para o Ccódigo do idioma. Em outras localidades (e em particular nas localidades do sistema normalmente definidas, como en_US.UTF-8), a ordem de agrupamento é algo assim aAbB ... zZque a-ztambém corresponde à maioria das letras maiúsculas. Além disso, a correspondência não está no nível de caracteres únicos, mas de "elementos de agrupamento", o que significa que em alguns locais, mesmocombinações de várias letraspode corresponder (por exemplo, dzsem húngaro)! Veresta resposta(ou, em geral, a maioria das respostas de @Stéphane Chazelas sobre correspondência de padrões) para obter mais informações. Se você quiser garantir que seus intervalos funcionem, defina a ordem de agrupamento pelo menos para o comando fornecido via

    LC_COLLATE="C" grep -E ' ... ' filename.txt
    

Responder2

+significa “uma ou mais repetições do anterior”, $é “fim de linha”. Observe a diferença versus *com significa “zero ou mais repetições”.

Então significa basicamente: Qualquer linha começando com um dígito, seguido por dois caracteres de qualquer tipo e posteriormente uma ou mais letras (possivelmente maiúsculas)¹ até o final da linha.

(¹ tenha cuidado, algumas localidades podem não ter apenas as 26 letras que você esperaria em AZ ou az, por exemplo, èou ŷdependendo do idioma)

Para um bom guia sobre regexes, sugiro fortementelindo site do grymoire, que também recomendo vivamente, por exemplo, sede awk.


Por que não corresponde?

+faz parte das expressões regulares estendidas (e, caso contrário, é interpretado como um +sinal literal).

Portanto, para usar +como "uma ou mais repetições", use o -E-flag grepe também cite o regex para evitar problemas com caracteres especiais do shell:

grep -E '^[0-9]..[a-zA-Z]+$' filename.txt

informação relacionada