명령 대체를 통해 배열에 여러 값을 할당하는 방법은 무엇입니까?

명령 대체를 통해 배열에 여러 값을 할당하는 방법은 무엇입니까?

다음 쉘 스크립트 함수를 고려하십시오.

#!/bin/bash

declare -a dir

function() {
local -a directories=( "A/B/C D" "E/F G H" ) #Initialize local array.
printf "%q " "${directories[@]}"             #"Return" values of array in escaped form.
}

dir=( $(funcion) )

for i in "${dir[@]}"; do
  echo $i
done

명령 대체가 작동하는 방법:

dir=( A/B/C\ D E/F\ G\ H ) #Escape the whitespace.

스크립트의 결과는 다음과 같아야 합니다.

A/B/C D
E/F G H

명령 대체가 실제로 작동하는 방식(결과 때문에 그렇게 생각합니다):

dir=( A/B/C\\ D E/F\\ G\\ H ) #Escape the backslash.

스크립트의 결과는 다음과 같습니다.

A/B/C\
D
E/F\
G\
H

나처럼 작동하게 하는 방법이 없을까?

답변1

내 생각에는 당신 \nprintf이것을 가지고 있습니다.

$ directories=( "A/B/C D" "E/F G H" )
$ printf "%q " "${directories[@]}"

이는 다음을 효과적으로 평가합니다.

$ printf "%q " "A/B/C D" "E/F G H"
A/B/C\ D E/F\ G\ H

이로 인해 for 루프가 A/B/C\, D, E/F\G\를 반복하게 됩니다 H.

대신 다음을 사용하는 경우 "%q\n":

$ printf "%q\n" "${directories[@]}"
A/B/C\ D
E/F\ G\ H

그런 다음 다음을 사용하여 결과( 에서 온다고 가정 func)를 배열로 읽을 수 있습니다.

readarray -t dir < <(func)

답변2

directories=( "A/B/C D" "E/F G H" ) #Initialize local array.
printf "%q " "${directories[@]}"

그러면 출력이 쉘 입력으로 사용하기에 적합하도록 인용된 값이 인쇄됩니다.

dir=( $(func) )

그러면 출력이 얻어지고 func, 토큰화 및 와일드카드를 통해 실행되고, 결과 필드가 배열에 저장됩니다.

호환되는 형식이 아닙니다. 특히 후자는 획득한 데이터를 다음과 같이 처리합니다.데이터, 따옴표, 이스케이프, 연산자 등과 같은 쉘 구문을 구문 분석하지 않습니다. 공백만 보입니다. (데이터의 백슬래시는 벗어날 수 없습니다. 애초에 특별한 의미가 없습니다.)

입력을 쉘 구문으로 처리하려면 를 통해 실행해야 eval하지만 이는 다른 것도 실행된다는 단점이 있습니다. 예를 들어 내장된 명령 대체가 실행됩니다(생각해 보세요 $(reboot)).

더 나은 접근 방식은 처음부터 데이터를 셸 구문으로 변환하지 않는 것입니다. 대신, 적절한 문자를 종결자로 사용하여 배열 값을 인쇄하고 프로세스 대체 read를 사용하여 readarray다시 읽습니다 .

예를 들어 개행 구분 기호를 사용하면 다음과 같습니다.

f() {
    printf "%s\n" "hello world" 'some"quotes\etc'
}
readarray -t arr < <(f)

또는 NUL 문자를 구분 기호로 사용하여 값에 개행 문자를 포함할 수 있습니다.

g() {
    printf "%s\0" "hello world" 'some"quotes\etc' $'two\nlines\n'
}
readarray -d '' -t arr < <(g)

(그런데 Bash에는 키워드가 있기 function() ...때문에 작동하지 않습니다 . 그러나 Dash와 Busybox에서는 작동하지만 배열에서는 작동하지 않습니다.)function

관련 정보