$ s=/the/path/foo.txt
다양한 기준을 통해 별도로 추출할 수 있습니다.
$ echo ${s##*/}
foo.txt
$ echo ${s%.txt}
/the/path/foo
하지만 동시에 두 가지 기준에 따라 추출하려면
$ echo ${${s##*/}%.txt}
bash: ${${s##*/}%.txt}: bad substitution
임시 변수를 도입하지 않고 매개변수 확장만으로 동일한 목표를 달성할 수 있습니까?
매개변수 확장이 다른 매개변수 확장 내에서 작동할 수 있나요?
감사해요.
답변1
다신 안 돼. Bash 또는 표준 쉘에서첫 번째 부분확장자는 다음과 같아야 합니다.범위(예: 변수, 위치 매개변수 또는 특수 매개변수 중 하나). 단순한 단어가 아닙니다.
불다:
매개변수 확장의 기본 형태는 ${범위}. 의 가치범위교체됩니다. 이것범위위에서 설명한 대로 쉘 매개변수 또는 배열 참조입니다.
이것POSIX의 텍스트여기서도 매개변수만 언급됩니다.
확장 프로그램을 사용할 수 있습니다다른 부분확장은 어떤 단어라도 될 수 있습니다. 그러나 이것은 물론 동일한 문자열에 대한 연결 작업에는 도움이 되지 않습니다(귀하의 예와 같이 ${${s##*/}%.txt}
).
$ bash -c 's=/the/path/foo.txt; ext=.tyt; echo "${s%${ext/y/x}}"'
/the/path/foo
Zsh는 명시적으로 지원합니다.그러나 링크는 다음과 같습니다.
대신 ${...} 유형 매개변수 표현식 또는 $(...) 유형 명령 대체를 사용하는 경우이름위에서는 먼저 확장하고 그 결과를 마치 확장한 것처럼 사용합니다.이름.
답변2
확장자가 없는 파일 이름 구성 요소(예: )를 단일 작업으로 찾는 경우 foo
RE 일치를 사용하여 경로에서 추출할 수 있습니다.
s=/the/path/foo.txt
[[ "$s" =~ (.*/)?(.*)\. ]]
echo "Got > ${BASH_REMATCH[2]} <" # "Got > foo <"
복합 표현식을 허용하지 않는 한 foo.bar.txt
확장자가 전혀 없는 파일 이름 구성 요소(예: )를 처리하면서 파일 이름에서 알 수 없는 가장 짧은 확장자를 제거하는 방법을 찾지 못했습니다.foo
[[ "$s" =~ (.*/)?(.*)(\.[^.]*)$ ]] || [[ "$s" =~ (.*/)?(.*) ]]
이렇게 하면 연속으로 두 번의 대체를 수행한 다음 떠나는 것이 더 효율적입니다.
s=/path/to/foo
f=${s##*/}
echo "${f%.*}"