매개변수 내에서 결과(파일명)를 기반으로 exec
정규식을 사용할 수 있습니까 find
? 예를 들어 다음과 같은 일부 매개변수를 기반으로 "실행"할 수 있기를 원합니다.
find . -name pattern -regex "foo (regex1) bar (Regex2)" -exec something $1 $2 ;
답변1
실행하려는 명령의 정규식에는 캡처링 그룹을 사용할 수 없습니다. 제한된 일치를 사용하는 경우 find -regex
명령에서 몇 가지 추가 일치를 수행해야 합니다. 셸을 호출하고 자체 패턴 일치 구문을 사용하여 이를 수행할 수 있습니다. 예를 들어, foo
및 bar
가 상수 문자열이고 다음과 regex1
일치할 수 없는 경우 bar
:
find … -exec sh -c '
x=${0#foo}
y=${x#*bar}
x=${x%%bar*}
something "$x" "$y"
' {} \;
셸을 호출하면 약간의 오버헤드가 발생합니다. 셸을 일괄적으로 호출하면 성능이 약간 향상될 수 있습니다.
find … -exec sh -c '
for item do
item=${item#foo}
y=${item#*bar}
x=${item%%bar*}
something "$x" "$y"
done
' sh {} +
regex1
몇 가지 필터링을 수행했으므로 및 를 초과하는 일치하는 셸 패턴으로 벗어날 수 있지만 regex2
특정 경로 형식의 경우 동일한 부분과 일치합니다. 일반 쉘 패턴으로 foo
및 를 표현할 수 없는 경우 bar
정규식만큼 강력한 추가 패턴인 , , 및 를 지원하는 ksh 또는 bash를 @(alter|native)
호출 *(zero-or-more)
할 수 +(one-or-more)
있습니다 .?(optional)
!(negated)
배쉬에서, 이러한 모드를 활성화해야 합니다 shopt -s extglob
. ksh에서는 로컬로 사용할 수 있습니다.
Bash에는 사용할 수 있는 정규식 일치 구문이 있습니다.조건문: [[ $STRING =~ REGEXP ]]
. 정규식은 ERE(예 find -regextype posix-egrep
: )입니다. (Zsh에는 비슷한 것이 있습니다. ksh는 있지만 =~
캡처 그룹을 노출하지 않습니다.) 캡처 그룹은 BASH_REMATCH
배열로 사용할 수 있습니다.
find … -exec bash -c '
for item do
[[ item =~ foo(regex1)bar(regex2) ]]
something "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
done
' bash {} +
또 다른 방법은결과 인쇄 및 필터링를 누른 다음 xargs
호출 프로그램을 호출합니다. 첫 번째와 두 번째 인수를 연속 용어로 정렬하고 실행합니다 xargs -n 2
. xargs의 이상한 인용 형식을 피하기 위해 널 바이트를 구분 기호로 사용하거나 -d '\n'
엄격한 라인별 구문 분석을 사용하십시오. sed와 같은 최신 GNU 도구는 레코드를 구분하기 위해 개행 문자 대신 널 바이트를 사용할 수 있습니다.
find … -print0 |
sed -z 's/^foo\(regex1\)bar\(regex2\)$/\1\x00\2/'
| xargs -n2 -0 something
또 다른 접근 방식은 ksh93, bash 또는 zsh의 재귀 와일드카드 기능 찾기를 포기하고 사용하는 것입니다. **/
하위 디렉터리를 재귀적으로 일치시킵니다. 이는 부울 커넥터가 포함된 복잡한 조회 표현식에서는 불가능하지만 대부분의 경우에는 충분합니다. 예를 들어, bash에서는 다음과 같이 디렉터리에 대한 심볼릭 링크로 반복됩니다 find -L
.
shopt -s extglob globstar
for x in **/*bar*; do
if [[ item =~ foo(regex1)bar(regex2) ]]; then
something "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
fi
done
zsh에서:
for x in **/*bar*; do
if [[ item =~ foo(regex1)bar(regex2) ]]; then
something $match[1] $match[2]
fi
done