특정 bash 함수가 정의 된 위치를 어떻게 찾을 수 있습니까?


답변:


32

디버깅을 켭니다. 에서 배쉬 설명서 :

극단

쉘 호출 또는 쉘 시작 파일에서 설정된 경우, --debugger옵션 과 동일하게 쉘이 시작되기 전에 디버거 프로파일을 실행하도록 정렬하십시오 . 호출 후 설정된 경우 디버거에서 사용하도록 의도 된 동작이 활성화됩니다.

  • -F받는 옵션 declare내장 (참조 : 갈라 내장 명령을 ) 인수로서 각 기능 명에 대응하는 소스 파일 이름 및 행 번호를 표시한다.

예:

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

그리고 실제로 :

$ 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()

이것은 훌륭하고 간단한 해결책입니다. 예를 들어 새 쉘을 시작할 필요조차 없습니다 shopt -s extdebug; declare -Ff quote; shopt -u extdebug.
jarno

2
@jarno 아, 내 이름과 달리 zsh를 사용합니다. 그래서 새로운 쉘을 시작했습니다. : D
bashity mcbashface

거기에 비슷한 찾을 수있는 방법 별칭 선언 위치는?
FedonKadifeli

@ 내 혼란스럽고 복잡한 접근법이 작동해야합니다.
terdon

1
이것을 다음과 같은 기능으로 만들 수 find_function()( shopt -s extdebug; declare -F "$@"; )있습니다. 함수 본문의 파렌을 사용하면 하위 쉘에서 실행되며 쇼핑객 변경이 호출자에게 영향을 미치지 않습니다. 그리고 -f필요하지 않은 것 같습니다.
wjandrea

15

이것은 실제로 처음보다 더 복잡합니다. 쉘이 읽을 파일은 현재 실행중인 쉘 유형에 따라 다릅니다 . 대화식인지 아닌지, 로그인 또는 비 로그인 쉘인지 여부와 위의 조합. 다른 쉘이 읽을 수있는 모든 기본 파일을 검색하려면 $functionName원하는 기능의 실제 이름으로 변경 하십시오.

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

그래도 작동하지 않으면 .또는 해당 별칭을 사용하여 기본이 아닌 파일을 호출하는 것일 수 있습니다 source. 이러한 경우를 찾으려면 다음을 실행하십시오.

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

아마도 설명이 필요할 것입니다. 그만큼-P 우리가 일부 애호가 정규식 구문을 사용할 수 있도록 펄 호환 정규 표현식 (PCRE)를 할 수 있습니다. 구체적으로 :

  • (^|\s): 줄의 시작과 일치합니다 (^ ) 또는 공백 ( \s) .
  • (\.|source)\s+: 리터럴 .문자 ( \.) 또는 단어 와 일치 source하지만 하나 이상의 공백 문자가 오는 경우에만 일치합니다 .

내 시스템에서 제공하는 내용은 다음과 같습니다.

$ 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

그러나 알 수 있듯이 일치하는 전체 줄이 인쇄됩니다. 우리가 실제로 관심을 갖는 것은 호출하는 파일이 아닌 호출 된 파일 이름의 목록입니다. 이보다 복잡한 정규 표현식을 가진 사람들을 얻을 수 있습니다.

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

-h플래그는 일치가 발견 된 파일 이름의 인쇄를 억제하는 grep여러 파일을 검색 할 말했을 때 기본적으로 수행합니다. -o수단 "은 라인의 정합 부를 인쇄". 정규식에 추가되는 추가 사항은 다음과 같습니다.

  • \K:이 시점과 일치하는 것은 무시하십시오. 이것은 복잡한 정규 표현식을 사용하여 일치하는 것을 찾을 수 있지만 grep을 사용할 때 일치하는 부분을 포함시키지 않는 PCRE 트릭입니다.-o 플래그를 .

내 시스템에서 위의 명령은 다음을 반환합니다.

$ 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

나는의 사용이 일어날 것을 참고 .하는 공백 없는 내가 다른 언어가 아닌 떠들썩한 파티를 호출 별칭을 가지고 있기 때문에 소싱을 위해 사용하지만, 그의를. 그게 이상 $a*100/$c하고")\n"' 위의 결과에 나오는 것입니다. 그러나 그것은 무시할 수 있습니다.

마지막으로 모든 기본 파일을 모아서 기본 파일 기본 파일이 소싱하는 모든 파일 에서 함수 이름을 검색하는 방법은 다음 같습니다.

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
}

해당 줄을 추가하고 ~/.bashrc실행할 수 있습니다 ( fooBar예제 함수 이름으로 사용 중).

grep_function fooBar

예를 들어, 내 줄 에이 줄이 있으면 ~/.bashrc:

. ~/a

그리고 파일 ~/a은 다음과 같습니다

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

나는 그것을 찾아야한다 :

$ grep_function fooBar
/home/terdon/a:fooBar(){

귀하의 솔루션은 훌륭한 교육용 스크립트 예제이지만 bashity mcbashface의 솔루션이 더 간단하다는 것을 알았습니다.
jarno

@ jarno 그리고 훨씬 간단합니다! :)
terdon

어레이 지원+=
D. Ben Knoble

@ D.BenKnoble 그들은? 배열의 첫 번째 요소에 array+="foo"문자열 foo을 추가하는 것 이외의 다른 의미 입니까?
terdon

1
@ D.BenKnoble 감사합니다! bash 배열이 그 표기법을 지원하는지 몰랐습니다!
terdon

2

보통 dotfile 사용자 별 bash읽기입니다 ~/.bashrc. 그러나 다른 파일을 매우 잘 소스 할 수 있습니다. 예를 들어 별명과 함수를 ~/.bash_aliasesand 라는 별도의 파일에 보관 ~/.bash_functions하면 훨씬 쉽게 찾을 수 있습니다. 다음 .bashrcsource사용하여 명령을 검색 할 수 있습니다 .

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

사용자가 만든 파일 목록이 있으면 파일과 사용자 .bashrc를 한 번의 grep호출로 검색 할 수 있습니다 ( 예 foo: 내 설정 기능) .

grep foo /home/USERNAME/.bash{rc,_aliases,_functions}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.