와일드카드와 중괄호 안에 지정된 확장 모음이 포함된 문자열을 확장하려고 합니다. 아래 예에서 설명한 것처럼 아무 것도 작동하지 않는 것 같습니다. 변수는 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
그게 왜 효과가 있나요?
그것이 왜 작동하는지 이해하는 것이 중요합니다. 확장 순서 때문이다. 먼저 "Brace 확장"과 나중에(마지막 확장) "Pathname Expansion"(일명 glob-expansion)입니다.
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
문제는 중괄호 확장에 변수를 사용할 수 없다는 것입니다.
이전에도 여러번 설명했지만"Brace Expansion" 내부의 변수 사용
"가변 확장"의 결과인 "보조 확장"을 확장하려면 를 사용하여 명령줄을 셸에 다시 제출해야 합니다 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
참고: 두 가지 솔루션(평가 및 패턴)(작성된 대로)은 공백이나 새 줄이 있는 파일 이름에 안전하다는 점에 유의하세요. 그러나 따옴표가 없거나 평가에서 따옴표를 제거하기 $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
확장 순서를 설명합니다.
확장 순서는 다음과 같습니다: 중괄호 확장; 물결표 확장, 매개변수 및 변수 확장, 산술 확장 및 명령 대체(왼쪽에서 오른쪽으로 수행됨) 단어 분리; 및 경로 이름 확장.