xargs가 바이너리 대신 별칭을 사용하도록 만들기

xargs가 바이너리 대신 별칭을 사용하도록 만들기

CentOS 6.5의 배시 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환경에서 별칭을 읽지 못하시나요 ?
  • 그렇지 않은 경우 이를 수행할 수 있는 방법이 있습니까?

답변1

사용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.

답변2

별칭은 해당 별칭이 정의된 셸 내부에 있습니다. 다른 프로세스에는 표시되지 않습니다. 쉘 기능도 마찬가지입니다. xargs셸이 아닌 별도의 애플리케이션이므로 별칭이나 기능에 대한 개념이 없습니다.

xargs가 쉘을 직접 호출하는 대신 쉘을 호출하도록 할 수 있습니다 grep. 그러나 단순히 셸을 호출하는 것만으로는 충분하지 않으며 해당 셸에서 별칭도 정의해야 합니다. 별칭이 쉘에 정의되어 있으면 파일을 얻을 수 있지만 비대화형 쉘에서는 의미가 없는 다른 작업을 수행 .bashrc하지 못할 수도 있습니다 ..bashrc

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

정규식을 입력할 때 중첩된 참조의 복잡성에 주의하세요. 정규식을 셸에 인수로 전달하면 생활을 단순화할 수 있습니다.

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 … 공백이 포함된 파일 이름은 무엇보다도 중단됩니다.. null로 구분된 레코드로 변경하면 이 문제를 해결할 수 있습니다.

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 이하의 경우 심볼릭 링크에서 재귀하고 싶지 않은 경우입니다. 이렇게 하면 공백이 포함된 파일 이름이 손상됩니다. 해결 방법은 다음과 같습니다.와일드카드 설정 IFS및 비활성화, 하지만 조금 복잡해지기 시작합니다.

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

답변3

관련 기사에서 찾을 수 없는 또 다른 접근 방식의 시연으로 이것을 받아들이십시오. 그래서 질문은:

xargs첫 번째 인수가 별칭인지 확인하고 그렇다면 그에 따라 확장하는 래퍼 함수를 ​​작성할 수 있습니다 .

여기에 정확하게 이를 수행하는 코드가 있지만 불행히도 이를 위해서는 다음이 필요합니다.Z 쉘따라서 bash로는 1:1을 실행하지 않을 것입니다(솔직히 저는 익숙하지 않습니다).세게 때리다이식하기에 충분합니다):

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]}"
}

작동하는지 증명하세요:

%별칭 grep="grep -n"'                          # 일치하는 줄 번호를 포함합니다
%foo -name "*.p*" 찾기 xargs grep -E test
foo/bar.p0:151:#data=테스트
foo/bar.p1:122:#data=test # 줄 번호를 포함합니다
%unalias grep
%foo -name "*.p*" 찾기 xargs grep -E test
foo/bar.p0:#data=테스트
foo/bar.p1:#data=test # 줄 번호를 포함하지 마세요
%

답변4

grep은 환경 변수 GREP_OPTIONS에서 기본 옵션 세트를 읽습니다. 넣을 수 있다면

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

.bashrc에서 변수는 서브쉘로 전달되고 예상한 결과를 얻게 됩니다.

관련 정보