Como criar uma frase expansível especial no bash?

12

Eu me vejo fazendo <command> --help | grep <feature>muito, muitas vezes todos os dias. Fiquei me perguntando se era possível fazer algo assim se ^^expande "--help | grep"e então faço isso:

ls ^^ size

Isso executaria o seguinte:

ls --help | grep size
yukashima huksay
fonte

Respostas:

17

Você pode usar uma função bash para isso:

Coloque o seguinte em seu ~ / .bashrc:

qh() {
    type -all "$1" ; { man "$1" || "$1" --help ;} | egrep -i -- "$2"
}

Quando você salva sua bashrc tarefa source ~/.bashrc, pode:

$ qh ls size
      --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                               '--block-size=M' prints sizes in units of
  -h, --human-readable       with -l and/or -s, print human readable sizes
  -s, --size                 print the allocated size of each file, in blocks
  -S                         sort by file size, largest first
      --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
tgwtdt
fonte
1
você deve citar $ 1 e $ 2. Eu mudaria isso para: qh () { type -all "$1" ; { "$1" --help || man "$1" ;} | egrep -i -- "$2" ;} # daí você pode: qh ls size, qh ls "something | another" etc. o (opcional) type -all "$1"também adiciona as informações sobre $ 1: diz se você estará lançando um alias, uma função, um de comando, etc. e dá fora informação do homem "$ 1" se o comando $ 1 não tem o "help" opção (isso acontece às vezes)
Olivier Dulac
1
@OlivierDulac Você pode explicar um pouco mais sobre o tipo -all "$ 1"? Em que caso será necessário?
tgwtdt 12/01
Minha versão do tipo (kubuntu 16.04) conhece -a, mas não diz nada sobre -lou -all, mas a função funciona.
Joe
15

Com zsh, você usaria um alias global :

$ alias -g '^^=--help|grep --color -i'
$ ls ^^ size
     --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
                              1,048,576 bytes; see SIZE format below
 -h, --human-readable       with -l and/or -s, print human readable sizes
 -s, --size                 print the allocated size of each file, in blocks
 -S                         sort by file size, largest first
     --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
 -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
The SIZE argument is an integer and optional unit (example: 10K is 10*1024)

Com bash, você poderá usar a expansão do histórico, que ocorre com bastante antecedência na análise de sintaxe do shell, para que possa funcionar na substituição de um canal:

  1. Prepare a história com o texto que você deseja substituir e um caractere especial que você provavelmente não utilizará (como £aqui, no meu teclado):

     $ --help $(: £)|grep
     bash: --help: command not found
     Usage: grep [OPTION]... PATTERN [FILE]...
     Try 'grep --help' for more information.
  2. Em seguida, use a expansão do histórico para recuperar isso:

    $ ls !?£? size
    ls --help $(: £)|grep size
         --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
     -h, --human-readable   with -l and/or -s, print human readable sizes
     -s, --size             print the allocated size of each file, in blocks
     -S                     sort by file size, largest first
         --sort=WORD        sort by WORD instead of name: none (-U), size (-S),
     -T, --tabsize=COLS     assume tab stops at each COLS instead of 8

Ou você pode readlineexpandir --help|grepcom alguma tecla ou sequência de teclas pressionada. Para que isso se aplique bashapenas (e não a outros aplicativos, como o gdbuso de readline), você pode usar o bindcomando bash builtin, que é basha API da configuração readline, por exemplo ~/.bashrc:

bind '"^^": "--help|grep "'

Ou adicione ao seu ~/.inputrc(arquivo de configuração da readline):

$if Bash
"^^": "--help|grep "
$endif

(existem outros shells como rcou esque usam readline e onde fazer essa ligação pode fazer sentido, mas AFAICT, eles não definem a rl_readline_namevariável antes da chamada, readlinepara que você não possa adicionar algumas $ifinstruções para eles (eles seriam exibidos othercomo todos os aplicativos que usam o readline sem informar o nome do aplicativo)).

Observe que você precisa inserir o segundo ^dentro de meio segundo (por padrão) após o primeiro para que a substituição ocorra.

Stéphane Chazelas
fonte
Você pode explicar um pouco mais a solução readline ?! onde devo adicionar essa ligação? em quais aplicativos essa ligação será expandida?
você precisa saber é o seguinte
@yukashimahuksay, consulte edit #
Stéphane Chazelas
8

Você pode usar ligações de linha de leitura:

adicione uma linha como

"^^": "--help | grep "

ao seu ~ / .inputrc

Em seguida, pressione ^ X ^ R no seu termo e a ligação será ativada.

A digitação ls ^^agora resultará em ls --help | grep.

Alex Stragies
fonte
Eu respondi antes de ver que Stephane havia adicionado a solução readline. Eu apaguei a minha resposta, mas depois undeletes, quando vi o comentário perguntando sobre detalhes para a solução readline
Alex Stragies
2
Agora adicionei um pouco mais sobre isso na minha resposta.
Stéphane Chazelas
1
Respostas específicas, como a sua, e abrangentes, como a de Stéphane, têm o seu lugar. Tenha um voto positivo!
bispo
5

Usando lesspara visualizar a mensagem de ajuda

Você pode achar útil ver o contexto circundante das linhas que correspondem à sua consulta de pesquisa.

hh () { "${1}" --help | less -p "${2}" ; }

A sintaxe para chamar essa bashfunção é semelhante à função qhna resposta de @ tgwtdt, com o primeiro argumento sendo o comando a ser examinado e o segundo argumento sendo o termo de pesquisa. Por exemplo:

hh ls size
hh ls "symbolic link"

Isso abre a mensagem de ajuda completa less, destaca todas as instâncias do termo de pesquisa e rola para a primeira instância do termo de pesquisa. Você pode pressionar npara rolar para a próxima linha que contém o termo de pesquisa, nnovamente para a próxima e assim por diante. Para voltar para uma instância anterior, pressione N. Use as Home, End, Page Up, Page Down, Up Arrow, e Down Arrowteclas para navegação geral. Pressione qou Qpara sair lesse retornar à linha de comando.

Gaultheria
fonte
3

Gostei da solução do @tgwtdt, então a aprimorei um pouco.

Isso faz a mesma coisa, mas faz um pouco para lidar com erros e também tenta processar embutidos.

qh usa () em vez de {}, então qh1 () e out são locais (em um subshell).

function qh () (
    function qh1 () {
      out="$(help "$1" 2>&1 )"
      [ $? -ne 0 ] && return 1
      echo "$out"
    }

    type -all "$1" ; { qh1 "$1" || "$1" --help 2>/dev/null || man "$1" 2>/dev/null ;} | egrep -i -- "$2"
) 
Joe
fonte