파일에서 읽은 여러 값 목록을 공백으로 구분된 값으로 처리하는 상당히 복잡한 쉘 스크립트가 있습니다.
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[@]}"
경우에도 작동하지만 . .