xargs가 바이너리 대신 별명을 사용하도록하십시오 강조 표시가 예상대로 작동합니다. $

CentOS 6.5의 Bash 4.2 :

내 안에는 다음을 ~/.bash_profile포함한 많은 별칭이 있습니다.

alias grep='grep -n --color=always'

실행할 때 색상 강조 표시를하고 줄 번호를 자동으로 인쇄 할 수 있습니다 grep. 다음을 실행하면 강조 표시가 예상대로 작동합니다.

$ grep -Re 'regex_here' *.py

그러나 최근에 이것을 실행했을 때 :

$ find . -name '*.py' | xargs grep -E 'regex_here'

결과가 강조 표시되지 않았고 줄 번호가 인쇄되지 않아서 돌아가서 명령에 명시 적으로 추가 -n --color=always해야했습니다 grep.

  • 않는 xargs환경에서 별칭을 읽을 수 없습니다?
  • 그렇지 않다면 그렇게 할 수있는 방법이 있습니까?


답변

별명은 정의 된 쉘 내부에 있습니다. 다른 프로세스에서는 볼 수 없습니다. 쉘 기능도 마찬가지입니다. xargs쉘이 아닌 별도의 응용 프로그램이므로 별칭 또는 함수 개념이 없습니다.

xargs가 grep직접 호출하는 대신 쉘을 호출하도록 할 수 있습니다. 그러나 쉘을 호출하는 것만으로는 충분하지 않으므로 해당 쉘에서 별명도 정의해야합니다. 에 별칭이 정의되어 있으면 .bashrc해당 파일을 소싱 할 수 있습니다. 그러나 .bashrc비 대화식 셸에서는 이해가되지 않는 다른 작업을 수행 하면 작동 하지 않을 수 있습니다.

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _

정규 표현식을 입력 할 때 중첩 인용의 복잡성을주의하십시오. regexp를 매개 변수로 쉘에 전달하여 수명을 단순화 할 수 있습니다.

find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here

별칭 조회를 명시 적으로 수행 할 수 있습니다. 그러면 xargs을 볼 수 grep -n --color=always있습니다.

find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here

zsh에서 :

find . -name '*.py' | xargs $aliases[grep] regex_here

그건 그렇고, find … | xargs … 공백이 포함 된 파일 이름 (다른 것들 중에서도)에 유의하십시오 . 널로 구분 된 레코드로 변경하여이 문제를 해결할 수 있습니다.

find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here

또는 -exec:

find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +

을 호출하는 대신 find쉘 내부에서 모든 것을 할 수 있습니다. glob 패턴 **/은 디렉토리를 재귀 적으로 탐색합니다. bash에서는 shopt -s globstar이 glob 패턴을 먼저 활성화 하기 위해 실행해야합니다 .

grep regex_here **/*.py

몇 가지 제한 사항이 있습니다.

  • 많은 파일이 일치하거나 긴 경로를 가진 경우 최대 명령 줄 길이를 초과하여 명령이 실패 할 수 있습니다.
  • bash ≤4.2 (최신 버전이나 ksh 또는 zsh는 아님)에서 **/디렉토리에 대한 심볼릭 링크로 반복됩니다.

또 다른 방법은 MariusMatutiae에서 제안한대로 프로세스 대체사용하는 것 입니다.

grep regex_here <(find . -name '*.py')

**/적용 할 수없는 경우에 유용합니다 . 복잡한 find표현식의 경우 또는 bash ≤4.2에서 심볼릭 링크 아래에서 재귀하지 않으려 는 경우에 유용 합니다. 공백이 포함 된 파일 이름이 끊어집니다. 해결 방법은 globbing설정 IFS및 비활성화하는 것이지만 약간 복잡해지기 시작합니다.

(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )


답변

사용하다 alias xargs='xargs '

alias: alias [-p] [name[=value] ... ]
(snip)
A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded.


답변

관련 SO 질문 에서 찾을 수없는 다른 접근법의 데모로 이것을 사용하십시오 .

xargs첫 번째 인수가 별명인지 확인하고 적절하면 확장 하는 랩퍼 함수를 ​​작성할 수 있습니다 .

여기에 있음을 정확히 수행하지만 불행히도 그것은 필요로하는 코드 Z 쉘을 bash는 1 (솔직히, 나는에 익숙하지 않아요 : 1 실행되지 않습니다 따라서 및 bash는 포트 그것으로 충분) :

xargs () {
        local expandalias
        if [[ $(which $1) =~ "alias" ]]; then
                expandalias=$(builtin alias $1)
                expandalias="${${(s.'.)expandalias}[2]}"
        else
                expandalias=$1
        fi
        command xargs ${(z)expandalias} "${(z)@[2,-1]}"
}

증명, 작동 :

zsh % alias grep = "grep -n"´                           # 일치하는 줄 번호 포함
zsh % find foo -name "* .p *"| xargs grep -E 테스트
foo / bar.p0 : 151 : # data = test
foo / bar.p1 : 122 : # data = test # 줄 번호 포함
zsh % unalias grep
zsh % find foo -name "* .p *"| xargs grep -E 테스트
foo / bar.p0 : # data = test
foo / bar.p1 : # data = test # 줄 번호는 포함되지 않습니다
zsh %


답변

더 간단하고 우아한 솔루션은 프로세스 대체 를 사용 하는 것입니다 .

grep -E 'regex_here' <( find . -name '*.py')

파이프처럼 새 쉘을 만들지 않습니다. 즉, 별칭이 정의 된 원래 쉘에 있고 출력이 원하는대로됩니다.

리디렉션과 괄호 사이에 공백이 없도록주의하십시오. 그렇지 않으면 bash가 오류를 발생시킵니다. 내가 아는 한, 프로세스 대체는 Bash, Zsh, Ksh {88,93}에 의해 지원되지만 pdksh에 의해 지원 되지않는다 (아직 말하면 안된다고 들었다 ).


답변

grep은 환경 변수 GREP_OPTIONS에서 기본 옵션 세트를 읽습니다. 당신이 넣을 경우

 export GREP_OPTIONS='--line-number --color=always'

.bashrc에서 변수는 서브 쉘로 전달되어 예상 결과를 얻을 수 있습니다.


답변