Por que o comando do pipe “l | grep ”1“ ”obtém o resultado errado?

13

Como a imagem ilustra, eu uso l para obter o arquivo na pasta atual. E então eu quero pegar o arquivo com o número 1 , então eu uso o pipe e o grep .

Mas por que o arquivo 2 e 22 é exibido? E qual é o 1;34m ?

$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22

Atualizar

Já alias o comando l no meu arquivo zshrc .

 alias lsp="ls"
 alias ll='ls -alF'
 alias la='ls -A'
 alias l='ls -CF'
 alias ls="ls -alh --color"

E aqui está o resultado do comando type :

>$ type ls
ls is an alias for ls -alh --color

> $ type l
l is an alias for ls -CF
    
por Lee 28.12.2016 / 04:38

3 respostas

27

Primeiro de tudo, o que você está tentando fazer, l| grep <filename> é ruim. Não faça isso. Aqui está o porquê.

O comando

l é realmente um alias para ls -CF

$ type -a l
l is aliased to 'ls -CF'

Por padrão, no bash do Ubuntu, ls é um alias para ls --color=auto . Como o Steeldriver apontou nos comentários, --color=auto deveria desativar a colorização. No seu caso específico, você tem alias ls="ls -alh --color" e alias l="ls -CF" , que basicamente acaba sendo ls -alh --color -CF . Essa combinação específica de switches ainda envia saída colorida em um pipe. Por exemplo:

$ ls -alh --color -CF ~/TESTDIR | cat -A                                                                                 
^[[0m^[[01;34m.^[[0m/  ^[[01;34m..^[[0m/  1.txt  2.txt  3.txt  out.txt$

Observe como os diretórios . e .. têm as mesmas sequências de escape.

O que isso tudo significa

Isso significa que l produzirá uma lista colorida de arquivos de acordo com o tipo de arquivo. O problema é que a colorização acontece com o uso de seqüências de escape . Isso é o que são 1:34m coisas - eles são seqüência de escape para cores específicas.

O principal problema é que a análise de ls geralmente leva a resultados e desastres errados em scripts, simplesmente porque ls permite sequências de escape, como explicado anteriormente, e outros caracteres especiais. Veja este artigo para mais informações: link

O que você deveria fazer:

Use o comando find :

bash-4.3$ ls
1.txt  2.txt  3.txt  out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt

Você poderia fazer algo assim com o shell glob e o teste moderno [[ command:

bash-4.3$ for file in * ;do if [[ "$file" =~ "1"  ]] ;then echo "$file" ;fi ; done
1.txt

Ou talvez use o python, que tem recursos de manuseio de arquivos muito melhores do que bash sozinho

bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']

Se não houver necessidade de processar a saída de ls , a simples globbing com ls também poderá funcionar. (Lembre-se, isso é apenas para visualizar a lista de arquivos, não para passá-lo para outro programa para lidar com o texto de saída)

bash-4.3$ ls *1*
1.txt
    
por Sergiy Kolodyazhnyy 28.12.2016 / 05:08
6

Seus comandos l e ls são configurados como aliases.

Quando você executá-los canalizando a saída por grep "1" (usando | ), cada linha de tela onde 1 aparece é exibida, com 1 colorido em vermelho.

Como os nomes de arquivos . , .. , 2 e 22 aparecem na mesma linha de tela, eles também saem em grep , mas não aparecem em vermelho, o que mostra grep correspondências.

O :34m é uma sequência de escape para uma cor que não é pintada corretamente. Com base na sua pergunta revisada com a saída de type -a l e type -a , ela pode ser reproduzida no meu sistema. Observe que você deve alterar seu alias de --color para --color=auto :

Saída de cores

    
por WinEunuuchs2Unix 28.12.2016 / 05:03
1

Em seu teste, você estava chamando seu ls alias, assim, o 1;34m e o ruído semelhante provenientes da coloração, e como o canal | recebe tudo isso na mesma linha, o grep corresponde ao arquivo 1 dessa linha e conseqüentemente imprime esta linha. Isso é o que você vê na tela.

Quando você está fazendo coisas assim, é sempre bom voltar ao comando do sistema com 1 resultado por linha.

Para se livrar dos aliases, basta digitar \ls e usar a opção -1 para imprimir os resultados separados por feeds de linha.

$ \ls -1 | grep "1"
1
11

Observação: o método da barra invertida funciona com todos os comandos, \command apenas chama o comando do sistema unaliased.

    
por pilko 28.12.2016 / 14:57