Por que o grep trata a string '[D] ebug' diferentemente?

4

Eu criei um arquivo de texto simples chamado "T" para testar o comportamento incomum de grep :

    1 Debug
    2 debug
    3 determined
    4 Determined

Tentei uma sintaxe diferente:

    $ grep De T
        1 Debug
        4 Determined
    $ grep de T
        2 debug
        3 determined
    $ grep Determined T
        4 Determined
    $ grep determined T
        3 determined
    $ grep Debug T
        1 Debug
    $ grep debug T
        2 debug
    $ grep [D]ebug T          # Why result is 2-nd line???
        2 debug
    $ grep [Dd]ebug T         # Why result is only one 2-nd line???
        2 debug
    $ grep [Dd]e T
        1 Debug
        2 debug
        3 determined
        4 Determined
    $ grep [d]e T
        2 debug
        3 determined
    $ grep [d]ebug T
        2 debug
    $ grep "[D]ebug" T
        1 Debug
    $ grep "[Dd]ebug" T
        1 Debug
        2 debug
    $ grep [\D]ebug T         # Why result is 2-nd line???
        2 debug
    $ grep --version
        grep (GNU grep) 2.16

Como você pode ver, quase todas as chamadas grep retornam resultado correto, mas $ grep [D]ebug T , $ grep [Dd]ebug T , $ grep [\D]ebug T retornam resultados errados. Por que isso está acontecendo?

    
por vedg 01.02.2014 / 13:55

1 resposta

7

Suponho que você provavelmente tenha um arquivo ou diretório chamado debug em seu diretório de trabalho atual:

 $ ls -l
total 8
-rw-r--r--   1 jay   wheel   58 Feb  1 05:01 T
 $ grep [D]ebug T
    1 Debug
 $ grep [Dd]ebug T
    1 Debug
    2 debug

 $ touch debug
 $ ls -l
total 8
-rw-r--r--  1 jay  wheel  58 Feb  1 05:01 T
-rw-r--r--  1 jay  wheel   0 Feb  1 05:05 debug

 $ grep [D]ebug T
    2 debug
 $ grep [Dd]ebug T
    2 debug

Eu recomendo esta excelente ilustração porque você deve sempre escapar dos metacaracteres do shell.

Atualização para esclarecer o que está acontecendo : Estou assumindo que, como eu, estamos usando um sistema operacional com um sistema de arquivos que não diferencia maiúsculas de minúsculas (por exemplo, um Mac). Quando você executa o comando, seu shell executa várias expansões antes de executar grep . Uma delas é expansão de nome de arquivo , na qual colchetes fornecem alternações:

[Dd]ebug em um sistema de arquivos sensível seria expandido para Debug debug , Debug ou debug dependendo de quais arquivos ele poderia corresponder. Como ele correspondia apenas ao arquivo debug , seu comando se tornou:

grep debug T

Se você remover esse arquivo e executar touch Debug , verá a saída do seu comando mudar, porque ele será interpolado como

grep Debug T

Sem o arquivo debug em seu diretório, seu shell tenta interpolar os colchetes, mas falha sem uma correspondência, por isso passa o argumento inalterado.

    
por 01.02.2014 / 14:10