AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / ubuntu / Perguntas / 1146269
Accepted
jarno
jarno
Asked: 2019-05-27 01:23:56 +0800 CST2019-05-27 01:23:56 +0800 CST 2019-05-27 01:23:56 +0800 CST

Como posso encontrar onde determinada função bash está definida?

  • 772

Existem muitas funções que podem ser usadas no shell Bash. Suas definições podem ser listadas por set, mas como descobrir em quais arquivos certas funções definidas pelo usuário estão definidas?

bash functions
  • 3 3 respostas
  • 2962 Views

3 respostas

  • Voted
  1. Best Answer
    bashity mcbashface
    2019-05-27T04:53:34+08:002019-05-27T04:53:34+08:00

    Ligue a depuração. Do manual do Bash :

    extdebug

    Se definido na chamada do shell ou em um arquivo de inicialização do shell, providencie a execução do perfil do depurador antes do início do shell, idêntico à --debuggeropção. Se definido após a chamada, o comportamento destinado ao uso por depuradores é ativado:

    • A -Fopção para o declarebuiltin (consulte Bash Builtins ) exibe o nome do arquivo de origem e o número da linha correspondente a cada nome de função fornecido como um argumento.

    Exemplo:

    $ bash --debugger
    $ declare -Ff quote
    quote 143 /usr/share/bash-completion/bash_completion
    

    E realmente:

    $ nl -ba /usr/share/bash-completion/bash_completion | sed -n 143,150p
       143  quote()
       144  {
       145      local quoted=${1//\'/\'\\\'\'}
       146      printf "'%s'" "$quoted"
       147  }
       148
       149  # @see _quote_readline_by_ref()
       150  quote_readline()
    
    • 36
  2. terdon
    2019-05-27T03:11:26+08:002019-05-27T03:11:26+08:00

    Na verdade, isso é mais complicado do que parece à primeira vista. Quais arquivos são lidos pelo seu shell depende do tipo de shell que você está executando no momento. Se é interativo ou não, se é um shell de login ou não e qual combinação dos itens acima. Para pesquisar todos os arquivos padrão que podem ser lidos pelos diferentes shells, você pode fazer (mude $functionNamepara o nome real da função que está procurando):

    grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
                         ~/.bash_aliases /etc/bash.bashrc /etc/profile \
                         /etc/profile.d/* /etc/environment 2> /dev/null
    

    Se isso não funcionar, você pode estar chamando um arquivo não padrão usando .ou seu alias source. Para encontrar esses casos, execute:

    grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
                                   ~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
                                   /etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
    

    Isso provavelmente precisa de alguma explicação. O -Phabilita Expressões Regulares Compatíveis com Perl (PCRE) que nos permite usar uma sintaxe de regex mais sofisticada. Especificamente:

    • (^|\s): corresponde ao início de uma linha ( ^) ou espaço em branco ( \s).
    • (\.|source)\s+: correspondem a um caractere literal .( \.) ou à palavra source, mas somente se forem seguidos por um ou mais caracteres de espaço em branco.

    Aqui está o que isso me dá no meu sistema:

    $ grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
    >                                ~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
    >                                /etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
    /home/terdon/.bashrc:   . /etc/bashrc
    /home/terdon/.bashrc:   . /etc/bash_completion
    /home/terdon/.bashrc:. $HOME/scripts/git-prompt.sh
    /home/terdon/.bashrc:#  echo -n "$n : "; grep "^CA"  $n |perl -e 'my ($a,$c)=0; while(<>){$c++;next if /cellular_component_unknown/; next if /biological_process/; $a++} print "$a Classes of $c annotated (" . $a*100/$c . ")\n"' 
    /etc/bash.bashrc:[ -r /usr/share/bash-completion/bash_completion   ] && . /usr/share/bash-completion/bash_completion
    /etc/profile:       test -r "$profile" && . "$profile"
    /etc/profile:   . /etc/bash.bashrc
    /etc/profile.d/locale.sh:    . "$XDG_CONFIG_HOME/locale.conf"
    /etc/profile.d/locale.sh:    . "$HOME/.config/locale.conf"
    /etc/profile.d/locale.sh:    . /etc/locale.conf
    /etc/profile.d/Z97-byobu.sh:        . /usr/bin/byobu-launch
    /etc/profile.d/Z97-byobu.sh:        . /usr/bin/byobu-launch
    /etc/profile.d/Z97-byobu.sh:        . /usr/bin/byobu-launch
    /etc/profile.d/Z97-byobu.sh:        . /usr/bin/byobu-launch
    /etc/profile.d/Z97-byobu.sh:        . /usr/bin/byobu-launch
    

    Como você pode ver, no entanto, isso imprimirá toda a linha correspondente. O que realmente nos interessa é a lista de nomes de arquivos chamados, não a linha que os está chamando. Você pode obtê-los com este regex mais complicado:

    grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
                                          ~/.bash.login ~/.bash_aliases \
                                          /etc/bash.bashrc /etc/profile \
                                          /etc/profile.d/* /etc/environment 2> /dev/null
    

    O -hsinalizador suprime a impressão dos nomes de arquivo onde uma correspondência foi encontrada, o que grepocorre por padrão quando solicitado a pesquisar em vários arquivos. Os -omeios "imprimem apenas a parte correspondente da linha". As coisas extras adicionadas ao regex são:

    • \K: ignore qualquer coisa correspondente até este ponto. Este é um truque de PCRE que permite usar um regex complexo para encontrar sua correspondência, mas não inclui a parte correspondente ao usar o -osinalizador do grep.

    No meu sistema, o comando acima retornará:

    $ grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
    >                                       ~/.bash.login ~/.bash_aliases \
    >                                       /etc/bash.bashrc /etc/profile \
    >                                       /etc/profile.d/* /etc/environment 2> /dev/null
    /etc/bashrc
    /etc/bash_completion
    $HOME/scripts/git-prompt.sh
    $a*100/$c
    ")\n"'
    /usr/share/bash-completion/bash_completion
    "$profile"
    /etc/bash.bashrc
    "$XDG_CONFIG_HOME/locale.conf"
    "$HOME/.config/locale.conf"
    /etc/locale.conf
    /usr/bin/byobu-launch
    /usr/bin/byobu-launch
    /usr/bin/byobu-launch
    /usr/bin/byobu-launch
    /usr/bin/byobu-launch
    

    Observe que tenho um uso de .seguido por um espaço que não é usado para sourcing, mas é porque tenho um alias que está chamando outro idioma, não o bash. É isso que dá estranho $a*100/$ce ")\n"'na saída acima. Mas isso pode ser ignorado.

    Por fim, veja como juntar tudo isso e procurar um nome de função em todos os arquivos padrão e em todos os arquivos que seus arquivos padrão estão fornecendo:

    grep_function(){
      target="$@"
      files=( ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login 
             ~/.bash_aliases /etc/bash.bashrc /etc/profile 
             /etc/profile.d/* /etc/environment)
        while IFS= read -r file; do
          files+=( "$file" )
        done < <(grep -hPo '(^|\s)(\.|source)\s+\K\S+'  "${files[@]}" 2>/dev/null)
        for file in "${files[@]}"; do
          ## The tilde of ~/ can break this
          file=$(sed 's|~/|'"$HOME"'/|g' <<<"$file")
          if [[ -e $file ]]; then
            grep -H "$target" -- "$file"
          fi
        done
    }
    

    Adicione essas linhas ao seu ~/.bashrce você poderá executar (estou usando fooBarcomo exemplo o nome da função):

    grep_function fooBar
    

    Por exemplo, se eu tiver esta linha no meu ~/.bashrc:

    . ~/a
    

    E o arquivo ~/aé:

    $ cat ~/a
    fooBar(){
      echo foo
    }
    

    Eu deveria encontrá-lo com:

    $ grep_function fooBar
    /home/terdon/a:fooBar(){
    
    • 18
  3. dessert
    2019-05-27T02:08:18+08:002019-05-27T02:08:18+08:00

    As leituras usuais de dotfile por usuário bashsão ~/.bashrc. No entanto, pode muito bem originar outros arquivos, por exemplo, gosto de manter aliases e funções em arquivos separados chamados ~/.bash_aliasese ~/.bash_functions, o que torna muito mais fácil encontrá-los. Você pode pesquisar os .bashrccomandos sourcecom:

    grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
    

    Depois de ter a lista de arquivos criados pelo usuário, você pode pesquisá-los e os do usuário .bashrccom uma única grepchamada, por exemplo, para função foopara minha configuração:

    grep foo /home/USERNAME/.bash{rc,_aliases,_functions}
    
    • 2

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Existe um comando para listar todos os usuários? Também para adicionar, excluir, modificar usuários, no terminal?

    • 9 respostas
  • Marko Smith

    Como excluir um diretório não vazio no Terminal?

    • 4 respostas
  • Marko Smith

    Como descompactar um arquivo zip do Terminal?

    • 9 respostas
  • Marko Smith

    Como instalo um arquivo .deb por meio da linha de comando?

    • 11 respostas
  • Marko Smith

    Como instalo um arquivo .tar.gz (ou .tar.bz2)?

    • 14 respostas
  • Marko Smith

    Como listar todos os pacotes instalados

    • 24 respostas
  • Martin Hope
    Flimm Como posso usar o docker sem sudo? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    led-Zepp Como faço para salvar a saída do terminal em um arquivo? 2014-02-15 11:49:07 +0800 CST
  • Martin Hope
    ubuntu-nerd Como descompactar um arquivo zip do Terminal? 2011-12-11 20:37:54 +0800 CST
  • Martin Hope
    TheXed Como instalo um arquivo .deb por meio da linha de comando? 2011-05-07 09:40:28 +0800 CST
  • Martin Hope
    Ivan Como listar todos os pacotes instalados 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    David Barry Como determino o tamanho total de um diretório (pasta) na linha de comando? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher "Os seguintes pacotes foram retidos:" Por que e como resolvo isso? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford Como os PPAs podem ser removidos? 2010-07-30 01:09:42 +0800 CST

Hot tag

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve