나는 다음 패턴을 사용하여 파일을 검색하는 것을 좋아합니다.
grep --color=auto -iRnHr --include={*.js,*.html,} --exclude-dir={release,dev,} "span" .
그러나 다음과 같이 bash 명령에 이를 포함하고 싶습니다.
findinfiles {*.js,*.html,} {release,dev,} "span" // syntax is just a guessing
$1
$2
이러한 유형의 중괄호를 bash 함수에 전달하고 , 등과 함께 사용하는 방법을 알 수 없습니다 . 다음을 사용할 때 :
function findinfiles() {
echo $1, $2, $3
}
그 다음에:
me@pc ~> findinfiles {*.js,*.html,} {release,dev,} "span"
*.js, *.html, release
물론 grep에 인수를 전달하는 것은 이런 방식으로 작동하지 않습니다. 매개변수가 색인화되었지만 올바르게 그룹화되지 않은 것 같습니다.
이런 유형의 논쟁을 처리하는 방법을 가르쳐 줄 수 있는 사람이 있습니까?
답변1
이것을 실행하면 findinfiles {*.js,*.html,} {release,dev,} "span"
다음과 같은 일이 발생합니다.
- Bash는 따옴표를 구문 분석하고 명령을 단어로 나눕니다:
findinfiles
,{*.js,*.html,}
{release,dev,}
span
. - Bash는 중괄호를 확장하여 , , ,
findinfiles
,*.js
, 단어 목록 을 생성합니다 .*.html
release
dev
span
- Bash는 와일드카드 패턴을 일치하는 파일 이름 목록
*.js
으로 확장합니다.*.html
두 패턴 중 어느 것과도 일치하는 파일 이름이 없으면 그대로 유지됩니다. - Bash는 name 을 조회하고
findinfiles
그것이 함수임을 확인한 다음 제공된 인수를 사용하여 함수를 실행합니다.
함수 호출 시 중괄호와 와일드카드의 확장을 방지할 수 있지만 중괄호는 인수에 문자 그대로 표시되므로 특히 유용하지 않습니다.
함수 호출 형식을 변경하는 것이 좋습니다. 중괄호를 사용하지 말고 쉼표만 사용하고 함수 내에서 인수를 쉼표로 수동으로 구분하세요.
findinfiles () {
local patterns="$1" excludes="$2" pattern="$3"
shift 3
typeset -a cmd dirs
if [[ $# -eq 0 ]]; then dirs=(.); else dirs=("$@"); fi
cmd=(grep --color=auto -iRnHr)
local IFS=,
for x in $patterns; do
cmd+=("--include=$x")
done
for x in $excludes; do
cmd+=("--exclude-dir=$x")
done
"${cmd[@]}" "${dirs}"
}
설명하다:
- 처음 세 개의 매개변수를 지역 변수에 저장합니다. 추가 인수는 검색할 디렉터리입니다.
dirs
추가 매개변수 목록으로 설정합니다 . 그렇지 않은 경우.
(현재 디렉터리)가 사용됩니다.쉼표로 설정합니다
IFS
. 스크립트$patterns
에 위와 같이 인용되지 않은 변수 확장이 포함된 경우$excludes
쉘은 다음을 수행합니다.- 변수를 해당 값으로 바꿉니다.
- 에 있는 문자가 포함될 때마다 변수를 별도의 단어로 분할합니다
IFS
. 기본적으로IFS
공백 문자(공백, 탭 및 줄 바꿈)가 포함됩니다. - 각 단어를 와일드카드 패턴으로 처리하고 일치하는 파일 목록으로 확장합니다. 일치하는 파일이 없으면 패턴이 유지됩니다.
(이러한 확장 단계를 피하려면
patterns="$1"
위 스크립트에서와 같이 변수 대체에 큰따옴표를 사용하십시오.)이 함수는 배열 변수에서 증분적으로 실행되도록 명령줄을 작성합니다
cmd
. 마지막으로 명령이 실행됩니다.
또는 다음 설정을 기반으로 빌드할 수 있습니다.
shopt -s extglob globstar
fif_excludes='release dev'
alias fif='grep --color=auto -inH $fif_excludes'
다음 명령을 실행하십시오.
fif span **/*.@(js|html)
설명하다:
shopt -s extglob
또는@(js|html)
일치하는 와일드카드 패턴 형식을 활성화합니다 . (이 옵션은 다른 모드 형식을 활성화합니다. 자세한 내용은 설명서를 참조하세요.)js
html
shopt -s globstar
모든 깊이의 하위 디렉터리와 일치하는 패턴을 활성화합니다**/
(예: 재귀 순회 수행).- 제외 목록(자주 발생하지는 않을 것으로 예상됨)을 변경하려면
fif_excludes
변수를 수정하십시오.
답변2
bash는 .. {a,b,}1
로 확장됩니다 a1 b1 1
.
귀하의 명령은 다음으로 확장됩니다 grep --color=auto -iRnHr --include=*.js --include=*.html --include= --exclude-dir=release --exclude-dir=dev --exclude-dir= span
(js 및 html 파일이 없는 디렉터리, 그렇지 않으면 모든 파일이 포함됩니다).
매개변수를 인용할 수 있지만 이는 이상적이지 않을 수 있습니다... findinfiles "{*.js,*.html,}" "{release,dev,}" "span"
(그러면 여전히 와일드카드가 필요합니다)
eval
그러면 다음 버전과 같이 를 사용하여 올바르게 확장할 수 있습니다 .
function findinfiles() {
eval "grep --color=auto -iRnHr --include=$1 --exclude-dir=$2 '$3'"
}