명령 결과를 출력 배열로 보내는 스크립트를 작성 중입니다. 여기에는 서버의 로그를 확인하고 해당 크기를 검색하는 작업이 포함되지만 경우에 따라 서버에 장애 조치 호스트가 있습니다. 이러한 경우 두 호스트를 모두 확인하고 값을 반환하는 스크립트가 필요합니다. 내가 겪고 있는 문제는 출력 배열 요소 중 하나라도 비어 있으면(검사 중인 파일이 서버에 존재하지 않고 해당 에코 디스플레이에 공백만 반환됨을 의미함) 이로 인해 배열 인덱스가 변경된다는 것입니다. 이는 보조 호스트 어레이 세트에 있어야 하는 항목이 기본 호스트 어레이 세트에 부딪히게 된다는 것을 의미합니다. 대신, 이동이 발생하지 않도록 이러한 빈 인덱스를 자리 표시자로 0으로 저장하고 싶습니다. 인덱스 오프셋이 분명해지는 곳은 다음과 같습니다.
echo The primary overall log value is ${output[0]}.
echo The primary obs log value is ${output[2]}.
echo The primary tracks log value is ${output[4]}.
echo
echo The secondary overall log value is ${output[6]}.
echo The secondary overall log value is ${output[8]}.
echo The secondary overall log value is ${output[10]}.
예를 들어 출력 [2]와 [4]가 비어 있으면 출력 [6]은 출력 [2]에 해당하는 행으로 위로 이동합니다. 이 솔루션을 시도했지만 운이 없습니다.
s=0
for x in "${output[@]}"
do(
x=
if [[ -z $x ]];
then(
x=0
echo $x)
else echo
fi
s=s+1)
done
이 모든 작업은 출력 에코가 발생하기 전에 0을 뱉어내고 인덱스 이동을 조정하지 않습니다.
참고: 출력 배열의 소스는 다음과 같습니다. 이를 수정하려는 시도는 다음과 같습니다.
for h in "${host[@]}"
do
for path in "${paths[@]}"
do
output+=( $(ssh $h du -sh $path) )
for x in "${!output[@]}";
do(
if [[ -z "${output[$x]}" ]];
then output[$x]=0;
fi;
)
done
done
done
호스트와 경로는 이미 정의된 배열입니다. 또한 액세스 가능한 호스트가 하나만 있으면 스크립트가 제대로 실행되고 배열 인덱싱에는 문제가 없다는 점도 확인했습니다.
답변1
예를 들어 출력 [2]와 [4]가 비어 있으면 출력 [6]은 출력 [2]에 해당하는 행으로 위로 이동합니다.
이 경우 실제로 2와 4를 null 값으로 바꾸는 것이 아니라 예상보다 적은 값을 가지게 됩니다.
배열 할당을 고려하십시오.
array1=(a b c d)
array2=(A D)
첫 번째는 , ~ 등 array1[0]
으로 설정됩니다. 두 번째는 및 로 설정 됩니다 . 와 사이에 null 값이 있어야 하는지 알 수 있는 방법이 없습니다 . 과제에 명시적으로 나타나야 합니다.a
array1[1]
b
array2[0]
A
array2[1]
D
A
D
array2=(A "" "" D)
다른 방법으로 배열을 채울 수도 있지만 output
그 방법을 보여주지 않았기 때문에 이에 대해 언급할 수 없습니다. 위와 비슷한 상황이 발생할 수 있습니다. "빈" 값은 배열을 채우는 어떤 값에서도 전혀 값으로 간주되지 않습니다 output
.
확장에서 배열에 할당하고 토큰화에 의존하는 경우 이를 피할 수 없습니다. (새 줄만 포함되어 있어도 IFS
연속된 빈 줄 바꿈을 하나로 축소하여 빈 줄을 제거합니다.) 를 사용하는 경우 mapfile
기본적으로 빈 줄이 배열 요소로 표시되어야 합니다.
어떤 경우든 빈 배열 요소를 0으로 만드는 루프는 루프 내부의 배열에 전혀 할당하지 않기 때문에 작동하지 않으며, 그렇게 했더라도 루프 본문은 하위 쉘(예: 괄호)에서 실행됩니다. (...)
), 따라서 모든 할당은 루프 본문 외부에서 발생하지 않습니다.
for x in "${output[@]}"
실제로 배열 요소를 효과적으로 수정하는 데 a를 사용할 수는 없습니다 . x
배열 값의 복사본만 가져오고 이를 수정해도 원래 값은 변경되지 않기 때문입니다. 배열을 가리키도록 배열 인덱스를 반복해야 합니다.
somearray=(1 "" "" 4)
for i in "${!somearray[@]}"; do
if [[ -z "${somearray[$i]}" ]]; then
somearray[$i]=0;
fi;
done
echo "${somearray[@]}"
인쇄 1 0 0 4
.
추가한 예제 코드에서 할당은 output+=( $(ssh $h du -sh $path) )
빈 요소를 추가하지 않습니다. 누락된 경로는 배열에서 생략됩니다. 먼저 생각해 보세요. du $path
경로가 존재하지 않으면 아무 것도 인쇄되지 않습니다. (stderr로 전송되고 명령 대체에 의해 포착되지 않는 오류는 제외.) 또한 빈 줄(또는 공백/탭)을 인쇄하더라도 토큰화는 연속 공백을 제거합니다.
예를 들어 array=( $( printf "foo\n\nbar\n" ) )
, 두 개의 요소가 있는 배열을 생성합니다.
또한 루프에서 괄호를 바꾸면 하위 쉘이 시작되므로 배열에 대한 수정 사항은 해당 하위 쉘 내에서만 적용됩니다. 일반적으로 말하자면, 당신은아니요특별히 하위 쉘이 필요하다는 것을 알지 않는 한 괄호를 사용하여 쉘 명령을 그룹화할 수 있습니다.
"$(ssh ... du)"
정확한 문자열을 얻기 위해 명령 대체( ) 주위에 따옴표를 넣을 수 있지만 경로 이름에서 크기를 분리할 수도 있습니다.
경로와 크기를 단일 배열로 수집하려면 다음과 같이 시도해 보세요.
for host in "${hosts[@]}"; do
for path in "${paths[@]}"; do
output="$(ssh "$host" du -sh "$path")"
size="${output%%$'\t'*}" # needs Bash/ksh/zsh
size="${size:-0}"
sizes+=( "$size" "$host:$path" )
done
done
이제 각 짝수 배열 요소에는 크기가 포함되고 각 홀수 배열 요소에는 분할 출력 du
결과와 다소 유사한 해당 호스트 이름과 경로가 포함됩니다. 두 인수는 탭 문자 뒤의 모든 항목을 확장 output
하고 제거한 다음 비어 있으면 크기를 0으로 바꿉니다.size
또는 다음을 빌드할 수 있습니다.연관 배열, 호스트 + 경로로 색인화됨:
declare -A array
...
array["$host:$path"]=$size