Pipe para o meu próprio script

1

Recentemente, notei esta mensagem do grep

"grep: warning: GREP_OPTIONS is deprecated; please use an alias or script"

Eu recebo este aviso porque --color = sempre está definido no meu arquivo .bashrc. O alias do AFAIK é impraticável, porque quero que isso funcione em um pipe. Por exemplo,

echo "a b c" |grep b

deve ser destacado b. Como um alias não funciona, a outra opção apresentada é criar um script. Mas como faço para que um script aceite entrada de um pipe? Nesse caso, quero o script append --color = always.

EDIT: Um alias funciona depois de tudo ... e o mesmo acontece com um script. Não tenho ideia do que estava fazendo de errado com o método de alias. No entanto, ao criar um script, inclua $ 1 no parâmetro de entrada.

Para qualquer pessoa que queira saber como enviar seu próprio script, neste exemplo, funcionou para mim fazendo o seguinte:

primeiro crie o script em um local no caminho para que ele seja executável, por exemplo,

# ~/.bin/testgrep
grep --color=always $1

Agora torne o script executável, por exemplo,

chmod +x ~/.bin/testgrep

Agora deve funcionar!

    
por Caezec 06.05.2015 / 04:30

2 respostas

-1

grep (ou seja, /bin/grep ) será lido na entrada padrão se for invocado sem argumentos de nome de arquivo. Portanto, é simples escrever um script que execute grep com entrada da entrada padrão - basta invocar grep sem argumentos de nome de arquivo. Mas grep deve receber (pelo menos) um argumento PADRÃO (ou equivalente). Uma maneira extremamente inflexível de fazer isso, que é improvável que seja muito útil na vida real, é codificar uma string de pesquisa (padrão) em seu script grep; por exemplo,

#!/bin/sh
grep --color=always cat

que pode ser usado no contexto

ps | mygrep

e provavelmente não muito mais. Um script ligeiramente mais flexível pode usar uma variável de ambiente como a string de pesquisa:

#!/bin/sh
grep --color=always $USER

que pode ser usado no contexto

ps -ef | mygrep

e provavelmente não muito mais. A única solução razoável, realista e robusta é permitir que o usuário do script para fornecer uma string de pesquisa como um argumento de linha de comando:

#!/bin/sh
grep --color=always $1

que pode ser usado no contexto

dmesg | mygrep TCP

e pode realmente ser bastante útil.

Bem, talvez eu deva dizer algo útil. Isso se desfaz rapidamente como você pode precisar de vários argumentos para especificar os parâmetros de pesquisa:

mygrep -i tcp                   Case-insensitive search; find tcp, TCP, Tcp, etc.
mygrep -v bash                  Find everything except bash.
mygrep -e cat -e dog            Find every line that contains cat or dog.
mygrep -f wordlist              Search strings are in a file.

O segundo esboço do nosso script pode ser:

#!/bin/sh
grep --color=always $1 $2 $3 $4 $5 $6 $7 $8 $9

que poderia lidar com qualquer um dos exemplos acima. Como um bônus extra, isso não precisa ser usado para ler a entrada padrão; podemos dizer

mygrep -i path .bashrc

e será executado

grep --color=always -i path .bashrc

Mas ainda não terminamos! Considere

mygrep  "cat food"  "shopping list.txt"

que será executado

grep --color=always cat food shopping list.txt

que irá (tentar) procurar por cat em três arquivos: food , shopping e list.txt . OK, podemos lidar com isso dizendo

#!/bin/sh
grep --color=always "$1" "$2"

mas

#!/bin/sh
grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"

não é uma boa resposta; vai virar

mygrep  "cat food"  "shopping list.txt"

em

grep --color=always  "cat food"  "shopping list.txt"  ""  ""  ""  ""  ""  "" ""

que fará o que você quiser, mas também emitirá sete mensagens de erro.

Então, o que fazer, o que fazer? Oh espere; Eu tenho uma marreta no meu armário:

#!/bin/sh
if [ "$1" = "" ]
then
    printf "%s\n" "error: mygrep must be run with at least one argument."
elif [ "$2" = "" ]
then
    grep --color=always "$1"
elif [ "$3" = "" ]
then
    grep --color=always "$1" "$2"
elif [ "$4" = "" ]
then
    grep --color=always "$1" "$2" "$3"
elif [ "$5" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4"
elif [ "$6" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5"
elif [ "$7" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6"
elif [ "$8" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7"
elif [ "$9" = "" ]
then
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8"
else
    grep --color=always "$1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"
fi

Certo.

  1. Isso é ridiculamente impraticável.
  2. Mesmo que falhe para

    mygrep  -e cat  -e dog  -e fish  file1  file2  file3  file4
    

    porque tem mais de nove argumentos! E, embora esta situação possa parecer improvável, o mesmo problema ocorre com

    mygrep  bird  *
    

    se houver mais de oito arquivos (não ocultos) no diretório atual.

Então, o que fazer, o que fazer?

TL; DR

Se você procurar em bash (1) em Parâmetros especiais , você verá que $@ se expande para a lista de parâmetros posicionais, começando de um. Quando a expansão ocorre entre aspas duplas, cada parâmetro se expande para uma palavra separada. Ou seja, "$@" é equivalente a "$1" "$2" … (conforme implementado no longo script, acima, mas não limitado aos primeiros nove). Então, a maneira de escrever um script para embrulhar (isto é, atuar como um front-end para) algum comando, agindo como um alias, é

#!/bin/sh
grep --color=always "$@"
    
por 06.05.2015 / 16:09
2

Um alias funcionará. Eu tenho grep aliased para grep --color=auto :

% which grep
grep: aliased to grep --color=auto

E o piping para o grep tem o comportamento que você deseja:

    
por 06.05.2015 / 04:41