[arrays] 요소에 공백이있는 배쉬 배열

카메라에서 파일 이름을 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[@]}"
...

로부터 배쉬 맨 페이지 :

배열의 모든 요소는 $ {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 루프를 사용하는 것도 좋으며 명확하지 않은 경우 단어 분리에 대해 걱정하지 않아도됩니다.

for (( i = 0; i < ${#FILES[@]}; i++ ))
do
  echo "${FILES[$i]}"
done


답변

탈출이 작동합니다.

#!/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

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


답변

원래 질문의 인용 / 이스케이프 문제에 대한 정확한 대답은 아니지만 실제로 op에 더 유용했을 것입니다.

unset FILES
for f in 2011-*.jpg; do FILES+=("$f"); done
echo "${FILES[@]}"

물론, 표현은 특정 요구 사항 (예 *.jpg를 들어 2001-09-11*.jpg, 특정 날짜의 그림 전체 또는 전체) 에 따라 채택되어야한다 .