file=/tmp/text/foo.txt
/bar
이제 매개변수 확장 구문을 사용하여 이 디렉터리 구조에 하위 폴더를 추가하고 싶습니다 . 이 줄의 작동 방식:
echo "${file%/*}/bar/${file##*/}"
이제 구문을 통해 더 짧게 만들 수 있는지 궁금합니다 ${parameter/%pat/string}
. /
as를 만들어서 pat
로 바꾸고 싶습니다 /bar/
. 하지만 어느 부분이 /
팻 부분인지 시스템에 어떻게 알릴 수 있는지 모르겠습니다 . 나는 그것을 탈출하려고 노력했지만 \
성공하지 못했습니다. 내가 작성한 코드는 다음과 같습니다.
echo "${f/%///bar/}"
또는
echo "${f/%\///bar/}"
그러나 그들 중 누구도 작동하지 않습니다.
답변1
사용역사적 수정.
for file in /tmp/text/foo.txt /foo.txt foo.txt mydir/; do
echo $file:h/bar/$file:t
done
시스템의 루트 디렉터리에 있는 파일이 //some/where
다르다는 점을 참고하세요 /some/where
. 특히 $file
디렉터리 부분이 전혀 없으면 작동하지만 순진한 버전은 ${file%/*}
그렇지 않습니다. $file
슬래시로 끝나면 비어 bar
있지 않은 마지막 경로 구성 요소 앞에 삽입됩니다. 이는 원하는 것일 수도 있고 아닐 수도 있습니다.
매개변수 확장 형식을 사용하면 다음을 사용할 수 있습니다.${VARIABLE/PATTERN/REPLACEMENT}
매개변수 확장 플래그 I
n번째 일치 항목을 선택하지만 안타깝게도 마지막 일치 항목에서는 선택할 수 없습니다. 이 특정 경우에는 작동 하지만 echo ${(I:3:)file/\///bar/}
디렉터리 수준이 몇 개인지 정확히 알아야 합니다. 다음을 셀 수 있습니다.
echo ${(I:${#file//[^\/]/}:)file/\///bar/}
그러나 이것은 여러 부분으로 나누는 것보다 더 복잡하고 슬래시가 없으면 더 잘 작동하지 않습니다 $file
.
활성화되면 다음을 extended_glob
사용할 수 있습니다.b
와일드카드 플래그패턴에서 슬래시가 아닌 문자를 일치시킬 수 있습니다(감사합니다.#
글로벌 운영자$match
)는 와일드카드 일치의 일부를 참조하는 데 사용됩니다 .
setopt extended_glob
for file in /tmp/text/foo.txt /foo.txt foo.txt mydir/; do
echo ${file/%(#b)([^\/]#)/bar/$match[1]}
done
패턴은 (#b)([^\/]#)
슬래시가 아닌 후행 문자와 일치하고 일치하는 부분을 에 저장합니다 $match[1]
. zsh ≥5.9를 사용하면 ${(*)file/%(#b)([^\/]#)/bar/$match[1]}
꺼져 있어도 쓸 수 있습니다. extended_glob
이는 간단하지는 않지만 견고하다는 장점이 있습니다. 즉, 디렉터리 부분이 없는 파일 이름의 일반적인 경우와 루트 디렉터리에 있는 파일의 극단적인 경우에도 결과가 정확합니다. 슬래시로 끝나는 mydir/bar/
경우 생성되며 원하는 것일 수도 있고 아닐 수도 있습니다.$file