나는 다음을 수행하고 싶습니다 -
bash-shell>echo (*).prop ; echo \1
분명히 위의 방법은 작동하지 않습니다. 그러나 이것이 가능한지, 그에 상응하는 것이 무엇인지 궁금합니다.
*
현재 디렉터리의 모든 파일과 일치하도록 쉘에 와일드카드를 사용 하고 싶습니다 . 물론, 위 검색을 .prop로 끝나는 파일로만 제한하세요. .prop 확장자가 없는 파일 이름을 캡처하고 역참조를 사용하여 인쇄합니다.\1
제가 추가한 예는 설명하기가 좀 간단합니다. 내 사용 사례는 더 복잡하지만 요구 사항을 충족하기 위한 역참조가 필요합니다.
답변1
ksh93은 AFAIK, ksh93 및 zsh 지원 캡처 그룹을 지원하는 역참조를 지원하는 유일한 셸입니다. 이는 여기서 찾고 있는 것과 비슷하지만 제안한 대로 사용할 수는 없습니다. (ksh93 \1
) 또는 $match[1]
(zsh)에는 일치하는 각 파일에 대해 캡처된 내용에 대한 참조가 필요합니다.
ksh93에서는 다음을 수행할 수 있습니다.
files=( ~(N)*.prop )
(( ${#files[@]} == 0 )) || printf '%s\n' "${files[@]/@(*).prop/\1}"
zsh에서:
set -o extendedglob
files=( *.prop(N) )
print -rC1 -- ${files/(#b)(*).prop/$match[1]}
연산자의 일부로 캡처 그룹에 대한 참조가 일치하는 각 파일에 대해 수행됩니다 ${array/pattern/replacement}
.
이는 zsh
val glob 한정자의 일부로 수행될 수도 있습니다 e
.
set -o extendedglob
print -rC1 -- *.prop(Ne['REPLY=${REPLY/(#b)(*).prop/$match[1]}'])
:r
확장을 제거하기 위한 전용 ootname 수정자가 있지만 :
print -rC1 -- *.prop(N:r)
Bash에서는 언제든지 다음을 수행할 수 있습니다.
shopt -s nullglob
files=( *.prop )
(( ${#files[@]} == 0 )) ||
printf '%s\n' "${files[@]%.prop}"
역참조는 기본 정규식 및 기타 정규식 엔진의 기능입니다.
bash
실제로 내장된 정규식 일치 연산자가 있지만 ERE(확장 정규식)를 사용한다는 점에 유의하세요. 표준 ERE는 역참조를 만들지 않지만 일부 구현에서는 이를 확장으로 지원합니다.
존재하다:
[[ aa =~ (.)\1 ]]
\1
표준 ERE 연산자가 아니기 때문에 그다지 효율적이지는 않지만 bash는 이를 \1
인용된 것으로 처리하여 1
시스템의 정규식 엔진을 (.)1
정규식으로 호출하기 때문입니다.
regexp='(.)\1'
[[ aa =~ $regex ]]
GNU 시스템과 같이 확장 정규식 엔진이 역참조를 지원하는 시스템에서 작동합니다.
여기에는 여러분이 원하는 것이 더 많이 포함되어 있으며, bash는 바로 그 일을 합니다.
성공 후
[[ $file =~ ^(.*)\.prop$ ]]
일치하는 콘텐츠는 (.*)
(배열의 두 번째 요소, zsh에서 캡처된 내용이 배열에 들어감)에서 사용할 수 있으므로 다음을 수행할 수 있습니다.${BASH_REMATCH[1]}
$BASH_REMATCH
$match
shopt -s nullglob
for file in *.prop; do
if [[ $file =~ ^(.*)\.prop$ ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
fi
done
( 예를 들어 파일 이름이 사용자의 로캘 문자 집합으로 인코딩되지 않은 경우 파일 실패가 *.prop
발생할 수 있습니다.)[[ $file =~ ^(.*)\.prop$ ]]
어쨌든 POSIX 셸에서는 \1
or와 동일합니다. 즉, 인용됩니다. 따라서 POSIX와 호환되도록 설계된 쉘은 POSIX가 이를 지정하지 않은 영역(예: ksh93에서 두 개의 동일한 문자로 시작하는 파일을 찾는 경우(따옴표가 없는 문자가 지정되지 않은 동작을 발생시키는 경우) 또는 이전에 언급한 경우에만 다른 의미를 부여할 수 있습니다. file은 POSIX 지정 연산자가 아닙니다.'1'
"1"
1
print -r -- @(?)\1*
(
)
"${files[@]/@(*).prop/\1}"
${array/pattern/replacement}
답변2
GNU 사용 basename
(또는 FreeBSD 또는 여러 단일 인수를 처리하고 각 인수에서 접미사를 제거하는 basename
비표준 -a
및 옵션을 제공하는 기타 구현에서):-s
basename -a -s .prop -- *.prop
*.prop
그러면 패턴과 일치 하지만 .prop
파일 이름 접미사가 제거된 파일 이름이 제공됩니다 .
제안한 것과 비슷한 것을 사용하십시오.
names=( *.prop )
printf '%s\n' "${names[@]%.prop}"
그러면 일치하는 모든 이름을 포함하는 배열이 생성됩니다 names
. 그런 다음 사용된 변수 대체는 각 이름을 출력하기 전에 printf
파일 이름 접미사를 제거합니다 ..prop
printf
배열에 로 끝나는 문자열만 포함되어 있다는 것을 알고 있으므로 .prop
두 번째 줄은 다음과 같이 단축될 수 있습니다.
printf '%s\n' "${names[@]%.*}"
그러면 배열의 각 문자열에서 마지막 점(및 점) 뒤의 모든 항목이 제거됩니다 names
.
쉘은 실제로 파일 이름을 일치시키기 위해 정규식을 사용하지 않습니다. 이는 파일 이름 글로빙 패턴을 통해 수행됩니다. 정규식은 파일의 텍스트를 일치시키는 데 더 일반적으로 사용됩니다.