Como mostrar o último comando com função de expansão no bash

3

Estou usando uma função como essa.

$ find-grep () { find . -type f -name "$1" -print0 | xargs -0 grep "$2" ; }

Depois de digitar:

$ find-grep *.c foo

Eu quero expandir a última string de comando. Neste caso:

find . -type f -name "*.c" -print0 | xargs -0 grep "foo"

Existe uma maneira de fazer isso facilmente?

    
por ironsand 21.09.2013 / 04:43

2 respostas

2

Uma versão melhor de @ slm:

find-grep() {
  cmd=(find . -type f -name "$1" -exec grep "$2" {})
  printf '%q ' "${cmd[@]}"
  printf '+\n'
  "${cmd[@]}" +
}

(não há necessidade de canos ou xargs aqui) ou:

find-grep () (
  set -x
  find . -type f -name "$1" -exec grep "$2" {} +
)

(observe o () em vez de {} para iniciar um subshell para limitar o escopo de set -x . Note que ele não causa mais processos a serem bifurcados, é apenas que fork para o processo que irá executar find é feito antes).

Lembre-se de citar caracteres curinga para que eles não sejam expandidos pelo shell:

find-grep '*.c' pattern

Se, em vez disso, você quiser que ele seja enviado ao histórico, para que você veja o comando expandido quando pressionar a tecla Acima , você poderá escrevê-lo:

find-grep() {
  cmd=$(printf '%q ' find . -type f -name "$1" -exec grep "$2" {})+
  history -s "$cmd"
  eval "$cmd"
}
    
por 21.09.2013 / 10:45
2

Aqui está uma maneira de fazer isso:

$ find-grep () {
  cmd=(find . -type f -name \"$1\" -print0 \| xargs -0 grep \"$2\")
  printf "%s\n" "${cmd[*]}" 
  eval "${cmd[*]}"
}

Exemplo

Veja alguns dados de amostra.

$ ls -l
total 8
-rw-rw-r-- 1 saml saml 4 Sep 21 10:44 1.c
-rw-rw-r-- 1 saml saml 4 Sep 21 10:44 2.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 3.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 4.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 5.c

Aqui está nossa função em ação, 2 dos arquivos contêm a string "foo".

$ find-grep '*.c' "foo"
find . -type f -name "*.c" -print0 | xargs -0 grep "foo"
./2.c:foo
./1.c:foo

Explicação

Esta versão particular da sua função faz as seguintes coisas de maneira diferente.

  1. Definimos uma variável com seu comando, $cmd=(find....) . O comando é empacotado em uma matriz, (..) .
  2. Ecoamos a matriz construída $cmd usando printf . Passamos os elementos da matriz usando a * notation, ${cmd[*]} , para que possamos obter a matriz como uma única string, em vez de uma lista discreta de elementos.
  3. Finalmente, avaliamos a matriz $cmd , que a executa.

Outra abordagem

Você também pode agrupar a função da seguinte forma: set -x ...function... set +x , que tem o efeito de ativar a depuração apenas pela duração de ...function... e desativá-la.

$ find-grep () { 
  set -x
  find . -type f -name "$1" -print0 | xargs -0 grep "$2"
  set +x
}

Exemplo

$ find-grep *.c foo
+ find . -type f -name '*.c' -print0
+ xargs -0 grep foo
+ set +x

Essa abordagem não é tão fácil de ler, mas está mostrando as mesmas funções pesadas, apenas quebradas com base em como elas foram executadas. Primeiro o find ... , seguido pelo xargs ... .

    
por 21.09.2013 / 04:51