나는 bash 스크립트에서 연관 배열의 마지막 몇 항목을 반복하려고 합니다. 이 경우에는 해당 값을 요약하기 위한 것입니다. 나는 다음을 시도했습니다 :
SUM="0"
for last_element in $(printf "%s\n" "${!ELEMENTS[@]}" | tail -100); do
ELEMENT_SUM="$(echo "scale=5; $SUM + ${ELEMENTS[$last_elements]}" | bc)"
done
실제로 일어나는 일은 $last_element
각 요소를 반복하는 대신 전체 목록(이 경우 100개 요소)을 인쇄한다는 것입니다. 따라서 ${ELEMENTS[$last_elements]}
실패합니다.
${ELEMENTS[-100]}
여러 가지 접근 방식(예: 음수 인덱싱 포함)을 시도했지만 성공하지 못했습니다. 내가 뭘 잘못하고 있는지 잘 모르겠습니다 ...
어떤 조언이나 아이디어라도 대단히 감사하겠습니다.
감사해요!
답변1
Bash의 연관 배열은 본질적으로 순서가 지정되어 있지 않으므로 마지막 요소 또는 마지막 100개 요소라는 개념이 없습니다.
그러나 의사 난수 순서로 배열에서 추출된 100개 요소의 값을 합산하려면 다음과 같이 하면 됩니다.
e100=$(printf "%s\n" "${elements[@]}" | tail -n 100)
sum=$(echo ${e100//$'\n'/+} | bc)
echo $sum
첫 번째 줄은 printf
연관 배열의 100개 요소를 개행 문자로 구분된 $elements
변수에 저장합니다 $e100
.
두 번째 줄은 echo
bash 인수 패턴 대체를 사용하여 모든 줄 바꿈을 기호로 변경한 다음 계산을 수행하기 위해 +
파이프로 연결합니다 . bc
결과는 변수에 저장됩니다 $sum
.
그건 그렇고, 이것은가치연관 배열을 직접 사용하면 배열의 인덱스를 반복할 필요가 없습니다.
이를 수행하는 더 좋은 방법이 있으며 "글쎄, 거기로 가고 싶다면 여기서 시작하지 않을 것"이라는 오래된 농담처럼 bash는 모든 종류의 데이터 처리에 대한 좋은 시작점이 아닙니다. awk, perl, python 또는 쉘이 아닌 거의 모든 것을 사용하십시오.
아마도 당신은 부동 소수점 숫자로 작업하고 있으며 bash가 정수 연산만 수행할 수 있다는 것을 깨달았으므로 bc
이 문제를 해결하기 위해 이를 사용하고 있을 것입니다. 그러한 기본 작업을 수행하는 데 따른 제한 사항을 해결할 필요가 없는 언어를 사용하는 것이 더 좋습니다.
답변2
bash 연관 배열(최신 버전 필요)은 임의의 키를 지원하지 않습니다. 또한 목록을 정렬하는 연산자가 없습니다(필요합니다).마지막의미 있음) 부동 소수점 연산을 수행할 수 없습니다.
여기서는 덜 제한적인 쉘(예: zsh)이나 적절한 프로그래밍 언어(예: Perl)를 사용합니다.
#! /usr/bin/perl
use List::Util "sum";
%elements = (
"foo" => 1.213,
"\0\n" => 0x12,
'' => -3,
"bar" => 1e-2
...
);
$sum = sum(map {$elements{$_}} (sort keys %elements)[-100 .. -1]);
#! /bin/zsh -
typeset -A elements
elements=(
foo 1.213
$'\0\n' 0x12
'' -3
bar 1e-2
...
)
set -o extendedglob
sum=$(( ${(@j[ + ])${(@ko)elements}[-100,-1]/(#m)*/$elements[$MATCH]} ))
이는 사전순으로 정렬된 마지막 100개 키 요소의 합계를 제공합니다( memcmp()
perl의 비교와 유사, strcoll()
zsh의 비교와 유사).
zsh를 사용하면 zsh에서 인식하는 모든 산술 표현식이 값이 될 수 있지만 value1 + value2 + ...
최종적으로 zsh에서 평가할 표현식을 작성할 때 우선순위에 유의하세요.
예를 들어 value1
is var = 3
및 value2
is 인 경우 4 || hash[$(some-cmd)]
결국 평가되고 var = 3 + 4 || hash[$(some-cmd)]
실행 되므로 값이 단순한 숫자 이상인 경우 some-cmd
값을 둘러싸도록 할 수 있습니다 .(...)