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에서 변수는 서브쉘로 전달되고 예상한 결과를 얻게 됩니다.