programing

요소에 공백이 있는 Bash 배열

minimums 2023. 5. 8. 22:01
반응형

요소에 공백이 있는 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

반응형