요소에 공백이 있는 Bash 배열
카메라에서 파일 이름을 사용하여 배열을 구성하려고 합니다.
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
보시다시피 각 파일 이름의 중간에 공백이 있습니다.
저는 각각의 이름을 따옴표로 묶고, 백슬래시로 공간을 탈출하려고 했지만, 둘 다 소용이 없습니다.
배열 요소에 액세스하려고 하면 공간이 요소 구분 기호로 계속 처리됩니다.
이름 안에 공백이 있는 파일 이름을 제대로 캡처하려면 어떻게 해야 합니까?
부분적으로는 요소에 액세스하는 방법에 문제가 있을 수 있습니다.제가 간단하게 하면,for elem in $FILES
저도 당신과 같은 문제를 겪고 있습니다.그러나 인덱스를 통해 배열에 액세스하는 경우에는 요소를 숫자로 추가하거나 이스케이프를 사용하여 추가하면 됩니다.
for ((i = 0; i < ${#FILES[@]}; i++))
do
echo "${FILES[$i]}"
done
이 선언들 중 하나는$FILES
작동해야 함:
FILES=(2011-09-04\ 21.43.02.jpg
2011-09-05\ 10.23.14.jpg
2011-09-09\ 12.31.16.jpg
2011-09-11\ 08.43.12.jpg)
또는
FILES=("2011-09-04 21.43.02.jpg"
"2011-09-05 10.23.14.jpg"
"2011-09-09 12.31.16.jpg"
"2011-09-11 08.43.12.jpg")
또는
FILES[0]="2011-09-04 21.43.02.jpg"
FILES[1]="2011-09-05 10.23.14.jpg"
FILES[2]="2011-09-09 12.31.16.jpg"
FILES[3]="2011-09-11 08.43.12.jpg"
배열의 항목에 액세스하는 방법에 문제가 있는 것 같습니다.방법은 다음과 같습니다.
for elem in "${files[@]}"
...
bash man 페이지에서:
${name[subscript]}을(를) 사용하여 어레이의 모든 요소를 참조할 수 있습니다. ...첨자가 @ 또는 *인 경우 단어는 이름의 모든 구성원으로 확장됩니다.이러한 첨자는 단어가 큰따옴표 안에 나타날 때만 다릅니다.단어가 이중 따옴표로 묶이면 ${name[*]}은(는) IFS 특수 변수의 첫 번째 문자로 구분된 각 어레이 멤버 값을 가진 단일 단어로 확장되고 ${name[@]}은(는) 이름의 각 요소를 별도 단어로 확장합니다.
물론, 단일 멤버에 액세스할 때도 큰따옴표를 사용해야 합니다.
cp "${files[0]}" /tmp
IFS를 사용하여 요소 구분 기호로 공백을 중지해야 합니다.
FILES=("2011-09-04 21.43.02.jpg"
"2011-09-05 10.23.14.jpg"
"2011-09-09 12.31.16.jpg"
"2011-09-11 08.43.12.jpg")
IFS=""
for jpg in ${FILES[*]}
do
echo "${jpg}"
done
.를 기준으로 분리하고 싶다면 IFS="를 사용하십시오." 도움이 되길 바랍니다.
문제가 되는 요소에 액세스하는 방법에 대한 다른 사람들의 의견에 동의합니다.배열 할당의 파일 이름을 따옴표로 묶는 것이 맞습니다.
FILES=(
"2011-09-04 21.43.02.jpg"
"2011-09-05 10.23.14.jpg"
"2011-09-09 12.31.16.jpg"
"2011-09-11 08.43.12.jpg"
)
for f in "${FILES[@]}"
do
echo "$f"
done
양식 배열 주위에 큰따옴표 사용"${FILES[@]}"
배열을 배열 요소당 하나의 단어로 나눕니다.그 이상은 말로 표현할 수 없습니다.
용사를 합니다."${FILES[*]}"
또한 특별한 의미가 있지만 배열 요소를 $IFS의 첫 번째 문자와 결합하여 하나의 단어를 생성합니다. 이는 아마도 사용자가 원하는 단어가 아닐 것입니다.
어사용 ${array[@]}
또는${array[*]}
그 확장의 결과를 추가적인 단어 확장으로 주어, 그래서 당신은 결국 공간에서 단어를 분할하게 될 것입니다(그리고 다른 모든 것).$IFS
배열 요소당 하나의 단어 대신 ).
루프에 C 스타일을 사용하는 것도 괜찮고 명확하지 않은 경우 단어 분할에 대한 걱정을 피할 수 있습니다.
for (( i = 0; i < ${#FILES[@]}; i++ ))
do
echo "${FILES[$i]}"
done
위에서 이미 답변한 내용인데, 그 답변은 좀 씁쓸하고 맨 페이지 발췌문은 좀 애매합니다.저는 이것이 실제로 어떻게 작동하는지 보여줄 수 있는 완벽한 사례를 제공하고자 했습니다.
따옴표로 묶지 않으면 배열이 공백으로 구분된 문자열로 확장되므로,
for file in ${FILES[@]}; do
로 확장됨.
for file in 2011-09-04 21.43.02.jpg 2011-09-05 10.23.14.jpg 2011-09-09 12.31.16.jpg 2011-09-11 08.43.12.jpg ; do
그러나 확장을 인용할 경우 bash는 각 항 주위에 큰따옴표를 추가하므로 다음과 같습니다.
for file in "${FILES[@]}"; do
로 확장됨.
for file in "2011-09-04 21.43.02.jpg" "2011-09-05 10.23.14.jpg" "2011-09-09 12.31.16.jpg" "2011-09-11 08.43.12.jpg" ; do
간한경법항칙것사입다니상는용하은험단을 사용하는 것입니다.[@]
에 [*]
공간을 보존하려면 배열 확장을 따옴표로 묶습니다.
더 하자면, 맨인용문이 좀더자히설자면하명세다, ▁if,$*
하나의$@
같은 방식으로 행동하지만 인용할 때는 다릅니다.가 주어집니다.
array=(a b c)
그리고나서$*
그리고.$@
다 로확니다됩으로 확장됩니다.
a b c
그리고."$*"
로 확장됩니다.
"a b c"
그리고."$@"
로 확장됩니다.
"a" "b" "c"
배열이 다음과 같은 경우: #!/bin/bash
Unix[0]='Debian'
Unix[1]="Red Hat"
Unix[2]='Ubuntu'
Unix[3]='Suse'
for i in $(echo ${Unix[@]});
do echo $i;
done
다음과 같은 이점이 있습니다.
Debian
Red
Hat
Ubuntu
Suse
왜 그런지는 모르겠지만 루프는 공간을 분해하여 개별 항목으로 배치합니다. 심지어 당신이 인용문으로 둘러쌉니다.
이 문제를 해결하려면 배열의 요소를 호출하는 대신 따옴표로 묶인 전체 문자열을 사용하여 인덱스를 호출합니다.따옴표로 묶어야 합니다!
#!/bin/bash
Unix[0]='Debian'
Unix[1]='Red Hat'
Unix[2]='Ubuntu'
Unix[3]='Suse'
for i in $(echo ${!Unix[@]});
do echo ${Unix[$i]};
done
그러면 다음을 얻을 수 있습니다.
Debian
Red Hat
Ubuntu
Suse
원래 질문의 인용/도피 문제에 대한 정확한 답변은 아니지만, 작업에 실제로 더 유용한 것일 수 있습니다.
unset FILES
for f in 2011-*.jpg; do FILES+=("$f"); done
echo "${FILES[@]}"
이 요구 되어야 하는 : 특정요예항사구에합채다니야택(예:) 해표대을현식해론물)예:).*.jpg
또는 전부를 2001-09-11*.jpg
특정한 날의 사진에 한함).
루프에 사용하는 대신 어레이를 한 줄 모드로 설정하는 것을 선호하는 사용자용
중IFS
일시적으로 새 라인으로 이동하면 탈출을 방지할 수 있습니다.
OLD_IFS="$IFS"
IFS=$'\n'
array=( $(ls *.jpg) ) #save the hassle to construct filename
IFS="$OLD_IFS"
탈출은 효과가 있습니다.
#!/bin/bash
FILES=(2011-09-04\ 21.43.02.jpg
2011-09-05\ 10.23.14.jpg
2011-09-09\ 12.31.16.jpg
2011-09-11\ 08.43.12.jpg)
echo ${FILES[0]}
echo ${FILES[1]}
echo ${FILES[2]}
echo ${FILES[3]}
출력:
$ ./test.sh
2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg
문자열을 따옴표로 묶으면 동일한 출력이 생성됩니다.
#! /bin/bash
renditions=(
"640x360 80k 60k"
"1280x720 320k 128k"
"1280x720 320k 128k"
)
for z in "${renditions[@]}"; do
echo "$z"
done
산출량
640x360 80k 60k
1280x720 320k 128k
1280x720 320k 128k
`
또 다른 해결책은 "for" 루프 대신 "while" 루프를 사용하는 것입니다.
index=0
while [ ${index} -lt ${#Array[@]} ]
do
echo ${Array[${index}]}
index=$(( $index + 1 ))
done
사용에 집착하지 않는 경우bash
파일 이름의 공간을 다르게 처리하는 것은 피쉬 쉘의 이점 중 하나입니다."ab.txt"와 "bc.txt"라는 두 개의 파일이 들어 있는 디렉터리를 생각해 보십시오.다음은 다른 명령에서 생성된 파일 목록을 처리하는 데 필요한 적절한 추측입니다.bash
파일 이름에 공백이 있기 때문에 실패합니다.
# bash
$ for f in $(ls *.txt); { echo $f; }
a
b.txt
b
c.txt
와 함께fish
구문은 거의 동일하지만 결과는 다음과 같습니다.
# fish
for f in (ls *.txt); echo $f; end
a b.txt
b c.txt
물고기는 명령어의 출력을 공백이 아닌 새 줄로 나누기 때문에 다르게 작동합니다.
만약 당신이 새로운 선이 아닌 공백으로,fish
에는 다음과 같은 매우 읽기 쉬운 구문이 있습니다.
for f in (ls *.txt | string split " "); echo $f; end
만약의 요소들이FILES
파일 이름이 다음과 같이 줄로 구분된 다른 파일에서 가져옵니다.
2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg
그런 다음 파일 이름의 공백이 구분 기호로 간주되지 않도록 이 작업을 수행합니다.
while read -r line; do
FILES+=("$line")
done < ./files.txt
다른 명령에서 가져온 경우 마지막 줄을 다음과 같이 다시 작성해야 합니다.
while read -r line; do
FILES+=("$line")
done < <(./output-files.sh)
IFS 값을 재설정하고 완료되면 롤백하곤 했습니다.
# backup IFS value
O_IFS=$IFS
# reset IFS value
IFS=""
FILES=(
"2011-09-04 21.43.02.jpg"
"2011-09-05 10.23.14.jpg"
"2011-09-09 12.31.16.jpg"
"2011-09-11 08.43.12.jpg"
)
for file in ${FILES[@]}; do
echo ${file}
done
# rollback IFS value
IFS=${O_IFS}
루프에서 가능한 출력:
2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-1108.43.12.jpg
언급URL : https://stackoverflow.com/questions/9084257/bash-array-with-spaces-in-elements
'programing' 카테고리의 다른 글
스위프트 언어로 된 추상 클래스 (0) | 2023.05.08 |
---|---|
단어 목록에 대한 PostgreSQL 와일드카드 LIKE (0) | 2023.05.08 |
vba에서 dim과 set의 차이점은 무엇입니까? (0) | 2023.05.08 |
프로그램에서 던져진 예외에 대한 강제 중단 (0) | 2023.05.08 |
자동 레이아웃을 사용하여 전체 너비의 백분율을 만드는 방법은 무엇입니까? (0) | 2023.05.08 |