와일드카드와 중괄호 안에 지정된 확장자 세트가 포함된 문자열을 확장하려고 합니다. 아래 예에서 볼 수 있듯이 아무 효과도 없는 것 같습니다. 변수는 firstList
잘 확장되지만, secondList
또는 은 올바르게 확장 thirdList
되지 않습니다 fourthList
. 나는 또한 다양한 버전을 시도했지만 eval
그 중 아무것도 작동하지 않습니다. 어떤 도움이라도 대단히 감사하겠습니다.
#!/bin/bash
touch a.ext1
touch b.ext1
firstList='*.ext1'
ls $firstList
touch a.ext2
touch b.ext2
secondList='*.{ext1,ext2}'
ls $secondList
ls '$secondList'
ls "$secondList"
thirdList=*.{ext1,ext2}
ls $thirdList
ls '$thirdList'
ls "$thirdList"
fourthList="*.{ext1,ext2}"
ls $fourthList
ls '$fourthList'
ls "$fourthList"
답변1
이것껍데기확장은 인용되지 않은 경우에만 발생합니다 *
. 인용하면 쉘이 확장되지 않습니다.
또한 셸에서 확장하려면 중괄호 확장을 인용 해제해야 합니다.
이것은 작동합니다(Echo를 사용하여 쉘이 무엇을 하는지 살펴보겠습니다).
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
다른 이름의 파일이 존재하는 경우에도:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
이것이 작동하는 이유는 무엇입니까?
그것이 왜 작동하는지 이해하는 것이 중요합니다. 이는 확장 순서 때문입니다. 먼저 "중괄호 확장"이 있고 마지막으로 "경로 이름 확장"(일명 glob 확장)이 있습니다.
Brace --> Parameter (variable) --> Pathname
"경로 이름 확장"을 일시적으로 끌 수 있습니다:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
"경로 이름 확장"은 *.ext1
및 의 두 가지 매개변수를 사용합니다 *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
문제는 변수를 사용하여 중괄호 확장을 수행할 수 없다는 것입니다.
이건 이전에도 여러번 설명했었죠"분기 확장"에서 변수 사용
"변수 확장"의 결과인 "중괄호 확장"을 확장하려면 를 사용하여 명령줄을 셸에 다시 제출해야 합니다 eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
지원 -->바꾸다--> 글로벌|-->지원하다-->변수-->전반적인 상황
........여기에 인용-->^^^^^^ ||평가^^^^^^^^^^^^^^^^^^^^^^^^^^
파일 이름 값은 평가 실행 문제를 일으키지 않습니다.
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
그러나 그 가치는 $list
안전하지 않을 수 있습니다. 그러나 값은 $list
스크립트 작성자가 설정합니다. 스크립트 작성자는 다음을 제어할 수 있습니다 eval
. 단지 외부에서 설정된 값을 사용하지 않는 것뿐입니다 $list
. 이 시도:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
더 나은 선택.
(평가 없이) 또 다른 옵션은 다음과 같습니다.Bash "확장 모드" 사용:
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
참고: 두 솔루션(평가 및 패턴)(작성된 대로)은 공백이나 줄 바꿈이 있는 파일 이름에 안전합니다. 그러나 따옴표가 없거나 eval이 따옴표를 제거하기 $list
때문에 공백이 있는 경우에는 실패합니다 .$list
답변2
고려하다:
secondList='*.{ext1,ext2}'
ls $secondList
문제는버팀대 확장이미 마쳤어앞으로 변수 확장. 이는 위의 경우 버팀대 확장이 수행되지 않음을 의미합니다.
이는 bash가 명령줄을 처음 볼 때 중괄호가 없기 때문입니다. 확장 후에 secondList
는 너무 늦을 것입니다.
다음이 작동합니다:
$ s='*'
$ ls $s.{ext1,ext2}
a.ext1 a.ext2 b.ext1 b.ext2
여기서 명령줄에는 다음과 같이 중괄호가 있습니다.버팀대 확장첫 번째 단계로 수행할 수 있습니다. 그 후, $s
(의 값을 대체합니다.변수 확장) 드디어경로명 확장처형되다.
문서
man bash
확장 순서를 설명하세요.
확장 순서는 중괄호 확장, 매개변수 및 변수 확장, 산술 확장, 명령 대체(왼쪽에서 오른쪽으로 수행됨)입니다.