Bash는 공백으로 구분된 목록을 관리합니다.

Bash는 공백으로 구분된 목록을 관리합니다.

파일에서 읽은 여러 값 목록을 공백으로 구분된 값으로 처리하는 상당히 복잡한 쉘 스크립트가 있습니다.

SET1="value1 value2 value3"

for i in ${SET1}; do
   ...

이제 스크립트에 비슷한 형식의 목록을 작성하여 작성하고 싶습니다. 그러나 다음과 같이 하면(예를 들어):

DISCOVERED=''
DISCOVERED+=( us-east-1 )
DISCOVERED+=( us-east-2 )
DISCOVERED+=( us-west-1 )
for REGION in ${DISCOVERED} ; do
    echo $REGION
done

나는 어떤 결과도 얻지 못한다. 지정하면 출력을 얻습니다 in ${DISCOVERED[@]}. SET1과 DISCOVERED에서 서로 다른 데이터 유형을 사용하고 있는 것 같습니다.

공백으로 구분된 값을 사용하여 문자열에 쉽게 추가할 수 있지만 정리해야 할 선행 또는 후행 공백이 생깁니다.

function append_discovered {
   local VALUE="$1"
   if [ -z "${DISCOVERED}" ] ; then
      DISCOVERED="$VALUE"
   else
      DISCOVERED="${DISCOVERED} ${VALUE}"
   fi
}

....하지만 꽤 번거로운 것 같습니다.

DISCOVERED="${DISCOVERED[@]}"출력 변수를 배열로 처리할 수 있지만 다른 목록과 다른 구성을 사용하여 이 목록을 반복하려면 해당 변수를 다시 변환() 해야 합니다 .

배열이 아닌 경우 입력 데이터의 데이터 유형은 무엇입니까(예: 위의 $SET1)?

이 목록을 추가하고 동일한 데이터 유형을 유지하는 더 깔끔한 방법이 있습니까?

답변1

SET1과 DISCOVERED에서 서로 다른 데이터 유형을 사용하고 있는 것 같습니다.

물론. SET1문자열입니다. 문자열 값을 공백으로 구분된 여러 요소로 해석할 수 있습니다. DISCOVERED반면에 여러 요소가 있는 배열이 있습니다.

set1='this is a string of seven words'
discovered=('this' 'is' 'an' 'array' 'with' 'seven' 'elements')

echo "$set1"
echo "${discovered[@]}"

SET1질문 상단에 있는 코드의 한 가지 문제점은 모든 요소가 와일드카드로 표시되고 확장된다는 것입니다. 따라서 현재 디렉터리에 있는 파일을 호출 onebananatwo하고 요소가 발견되면 one*와일드카드는 one*로 확장됩니다 onebananatwo. (이런 일이 발생하지 않도록 하려면 변수에 큰따옴표를 사용하는 것이 좋습니다.)

공백으로 구분된 값을 사용하여 문자열에 쉽게 추가할 수 있지만 정리해야 할 선행 또는 후행 공백이 생깁니다.

문자열이 비어 있지 않은 경우에만 조건부 확장을 사용하여 공백을 삽입할 수 있습니다.

append_discovered() {
    local value=$1
    discovered="$discovered${discovered:+ }$value"
}

function( 실수로 예약된 변수와 충돌하지 않도록 비표준 키워드를 제거하고 변수 이름을 소문자로 지정했습니다 .)

다음과 같은 일이 발생합니다 $discovered${discovered:+ }$value.

  • $discovered빈 문자열인 경우 빈 ${discovered:+ }문자열도 반환되므로 결과는 다음과 같습니다.$value
  • $discovered값이 있으면 공백 ${discovered:+ }이 반환되므로 결과는 단일 공백 $discovered으로 구성되고 구분된 문자열 입니다.$value

앞으로는 문자열에서 공백으로 구분된 요소 대신 배열을 배열 데이터 유형으로 사용하는 것을 고려하는 것이 좋지만 이를 기존 스크립트에 다시 설치하는 것이 비용 효율적이거나 현명하지 않을 수 있다는 것을 알고 있습니다.

답변2

내 Mac의 bash 5.x에서는 첫 번째 구문이 작동합니다.

DISCOVERED=''
DISCOVERED+=( us-east-1 )
DISCOVERED+=( us-east-2 )
DISCOVERED+=( us-west-1 )
echo ${#DISCOVERED[@]}
printf '"%s" ' "${DISCOVERED[@]}"
echo

출력은 다음과 같습니다

4
"" "us-east-1" "us-east-2" "us-west-1"

DISCOVERED=''첫 번째 요소를 빈 문자열로 설정하는 대신 해당 명령문에서 모든 배열 요소를 삭제하도록 하여 첫 번째 배열 요소를 확장/반환하려고 하면 배열이 비어 있는 것처럼 보이도록 할 수 있습니까 ?

배열 변수가 지워졌는지(요소 없음) 확인하려면 DISCOVERED=()또는 를 권장합니다 unset DISCOVERED.

다음을 추가하도록 편집되었습니다.

배열 요소에서 구분된 문자열을 생성하려면 일반적으로 간단한 두 줄을 사용합니다. 이 예에서는 ' :'를 구분 기호로 사용합니다.

printf -v SET1 '%s:' "${DISCOVERED[@]}"
SET1="${SET1%:}"
echo $SET1

(빈 첫 번째 배열 요소는 포함하지 않았습니다.) 출력:

us-east-1:us-east-2:us-west-1

내장 속성을 사용하여 printf배열 요소를 반복하고 각 요소에 구분 기호를 추가합니다. (만세, 루프를 작성할 필요가 없습니다!) 두 번째 줄은 마지막 구분 기호를 제거합니다. 이 방법은 공백 문자를 구분 기호로 사용하는 SET1="${DISCOVERED[@]}"경우에도 작동하지만 . .

관련 정보