다음과 같이 $basename
두 부분의 출력 $stem
합계가 포함된 문자열을 분할하고 싶습니다 .$ext
- 이 문자열은
"${stem}${ext}"
원래 문자열과 동일합니다$basename
. - 또는 비어 있을
$stem
수$ext
있습니다( 의 문자열에 따라 다름$basename
). - 비어 있지 않으면
$ext
다음으로 시작하고.
더 이상 포함할 수 없습니다..
이를 위해 쉘 함수를 작성하는 것은 어렵지 않습니다. 그러나 그렇게 하기 전에 이를 수행할 수 있는 표준 Unix 명령이 있는지 알고 싶습니다.
편집하다:
FWIW, () 스크립트에서 내가 코딩한 방식은 zsh
다음과 같습니다.
stem=${basename%.*}
ext=${basename#"$stem"}
편집: 오타( ${base#...
-> ${basename#...
)를 수정하고 Stephane Chazelas의 제안( ...#$stem
-> ...#"$stem"
)을 통합했습니다.
답변1
Bash에 포함된 일반적인 문자열 구문 분석 기능을 사용하여 원하는 것에 매우 근접하게 작업을 수행할 수 있습니다.
$ F="foo.bar.baz"
$ echo ${F%.*}
foo.bar
$ echo ${F/*./.}
.baz
따라서 다음과 같이 정리할 수 있습니다.
$ $ F="foo.bar.baz"
$ stem=${F%.*}
$ ext=${F/*./.}
echo "${stem}${ext}"
foo.bar.baz
Bash 매뉴얼 페이지에서
${F%.*}${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern
just as in pathname expansion. If the pattern matches a trailing portion
of the expanded value of parameter, then the result of the expansion is
the expanded value of parameter with the shortest matching pattern (the
``%'' case) or the longest matching pattern (the ``%%'' case) deleted. If
parameter is @ or *, the pattern removal operation is applied to each
positional parameter in turn, and the expansion is the resultant list.
If parameter is an array variable subscripted with @ or *, the pattern
removal operation is applied to each member of the array in turn, and
the expansion is the resultant list.
${/*./.}
${parameter/pattern/string}
Pattern substitution. The pattern is expanded to produce a pattern just
as in pathname expansion. Parameter is expanded and the longest match of
pattern against its value is replaced with string. If pattern begins
with /, all matches of pattern are replaced with string. Normally
only the first match is replaced. If pattern begins with #, it must match
at the beginning of the expanded value of parameter. If pattern begins
with %, it must match at the end of the expanded value of parameter.
If string is null, matches of pattern are deleted and the / following
pattern may be omitted. If parameter is @ or *, the substitution operation
is applied to each positional parameter in turn, and the expansion
is the resultant list. If parameter is an array variable subscripted
with @ or *, the substitution operation is applied to each member of the
array in turn, and the expansion is the resultant list.
이러한 기능에 대한 내용은 다음에서 읽을 수 있습니다.배쉬 매뉴얼 페이지.
답변2
쉘 변수를 설정하는 명령은 있을 수 없습니다. 왜냐하면 변수는 쉘 프로세스 내부에 있는 것이므로 자체 프로세스에 있는 다른 명령이 이를 변경할 수 없기 때문입니다.
셸을 사용하면 다음을 수행할 수 있습니다.
var=$(some-command)
명령의 출력을 검색합니다(후행 개행 없이). 그러나 명령의 두 결과가 모두 필요한 경우에는 더 까다로워집니다.
이를 수행하는 한 가지 방법은 다음과 같습니다.
eval "$(some-command)"
그중 some-command는 다음 내용을 출력합니다.
var1='something' var2='someotherthing'
그러나 물어보기 전에 경로를 가져와서 이를 디렉터리, 기본 이름 및 확장명(그게 무엇을 의미하든)으로 분할하는 표준 명령은 없습니다.
이제 셸 자체에는 이 목적을 위한 내부 기능이 있을 수 있습니다. 예 csh
를 들어 zsh
머리, 꼬리, 확장을 제공하는 수정자가 있습니다. 그림 zsh
:
file=/path/to/foo.bar/
head=$file:h
tail=$file:t
ext=$file:e
rest=$file:r
.
..
이제 or , /
또는 .bashrc
과 같은 파일에 대해 이것이 무엇이어야 하는지 생각해 보고 싶을 수도 있습니다 foo.tar.gz
.
이제 표준 POSIX 구문을 찾고 있다면 이미 (거의) 그것을 가지고 있습니다: rest=${file%.*}
. 구체적 ${file#$rest}
으로 말하세요 zsh
. POSIX 구문에서는 가 필요하며 ext=${file#"$rest"}
, 그렇지 않으면 $rest
패턴으로 처리됩니다. 문자 (예 : ) $file
가 포함된 경로를 포함 하면 원하는 대로 작동하지 않을 수 있습니다./
foo.d/bar
답변3
문자열에 개행 문자가 포함되어 있지 않은 경우:
start cmd:> echo foo.bar.baz | sed 's/\(^.*\)\(\.[^\.]*$\)/\1/'
foo.bar
start cmd:> echo foo.bar.baz | sed 's/\(^.*\)\(\.[^\.]*$\)/\2/'
.baz
답변4
"foo.bar"라고 합시다. ext가 누락되고 항상 2~3개의 마침표가 있는 경우 유효한 출력입니다.앗:
basename='foo.bar.baz'
stem=$(echo $basename | awk '{ split($1,a,"."); print a[1] "." a[2]; }')
ext=$(echo $basename | awk '{ split($1,a,"."); print "." a[3]; }');
echo $stem$ext