IT

Bash 루프의 카운터 증가가 작동하지 않습니다.

lottoking 2020. 7. 18. 09:44
반응형

Bash 루프의 카운터 증가가 작동하지 않습니다.


루프를 실행하고 유지하려는 다음 간단한 펼쳐보기가 COUNTER있습니다. 카운터가 업데이트되지 않는 이유를 알 수 없습니다. 서브 쉘이 생성 되었습니까? 이 문제를 어떻게 해결합니까?

#!/bin/bash

WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' |
(
while read WFY_URL
do
    echo $WFY_URL #Some more action
    COUNTER=$((COUNTER+1))
done
)

echo $COUNTER # output = 0

첫째, 카운터를 늘리지 또는 COUNTER=$((COUNTER))변경 하면 증가합니다.COUNTER=$((COUNTER + 1))COUNTER=$[COUNTER + 1]

둘째, 추측 할 때 서브 쉘 변수를 당신에게 역 전파하는 것이 더 까다 롭습니다. 서브 쉘의 변수는 서브 쉘 외부에서 사용할 수 없습니다. 약간 마이 색 프로세스에 로컬 인 변수입니다.

이를 해결하는 한 가지 방법은 임시 파일을 사용하여 중간 값을 저장하는 것입니다.

TEMPFILE=/tmp/$$.tmp
echo 0 > $TEMPFILE

# Loop goes here
  # Fetch the value and increase it
  COUNTER=$[$(cat $TEMPFILE) + 1]

  # Store the new value
  echo $COUNTER > $TEMPFILE

# Loop done, script done, delete the file
unlink $TEMPFILE

COUNTER=1
while [ Your != "done" ]
do
     echo " $COUNTER "
     COUNTER=$[$COUNTER +1]
done

테스트 된 BASH : Centos, SuSE, RH


COUNTER=$((COUNTER+1)) 

현대 프로그래밍에서 서투른 구성입니다.

(( COUNTER++ ))

더 "현대"보인다. 당신은 또한 사용할 수 있습니다

let COUNTER++

가독성이 향상되면 생각하면 Bash가 너무 많은 방식으로 작업을 수행합니다 -Perl 철학-아마도 역시 "올바른 방법은 하나뿐"일 때 더 적합 할 수 있습니다. 그것이 있다면 그것이 주장의 여지가있는 주장입니다! 어쨌든 목표 (이 경우)는 변수를 늘리는 것이 아니라 다른 사람이 이해하고 지원할 수있는 코드를 작성하는 것 (일반 규칙)을 제안합니다. 그것을 달성하기 위해 먼 길을 간다.

HTH


사용하려고

COUNTER=$((COUNTER+1))

대신에

COUNTER=$((COUNTER))

count=0   
base=1
(( count += base ))

이 단일 awk 호출은 grep|grep|awk|awk파이프 라인 과 동일하다고 생각 합니다. 테스트하십시오. 마지막 awk 아무것도하지 않습니다.

COUNTER의 문제점은 while 루프가 서브 쉘에서 실행 중이므로 서브 쉘이 종료 될 때 변수에 대한 변경 사항이 사라진다는 것입니다. 동일한 서브 쉘에서 COUNTER의 값에 액세스해야합니다. 또는 @DennisWilliamson의 조언을 따르고, 프로세스 대체를 사용하고, 서브 쉘을 완전히 피하십시오.

awk '
  /GET \/log_/ && /upstream timed out/ {
    split($0, a, ", ")
    split(a[2] FS a[4] FS $0, b)
    print "http://example.com" b[5] "&ip=" b[2] "&date=" b[7] "&time=" b[8] "&end=1"
  }
' | {
    while read WFY_URL
    do
        echo $WFY_URL #Some more action
        (( COUNTER++ ))
    done
    echo $COUNTER
}

임시 파일을 사용하는 대신 while프로세스 대체를 사용하여 루프 주위에 서브 쉘을 작성하는 것을 피할 수 있습니다 .

while ...
do
   ...
done < <(grep ...)

그건 그렇고, 당신은 모든 것을 grep, grep, awk, awk, awk하나의 awk.

Bash 4.2부터는 다음과 같은 lastpipe옵션이 있습니다.

현재 셸 컨텍스트에서 파이프 라인의 마지막 명령을 실행합니다. lastpipe 옵션은 작업 제어가 활성화 된 경우 효과가 없습니다.

bash -c 'echo foo | while read -r s; do c=3; done; echo "$c"'

bash -c 'shopt -s lastpipe; echo foo | while read -r s; do c=3; done; echo "$c"'
3

미니멀

counter=0
((counter++))
echo $counter

이것이 당신이해야 할 전부입니다 :

$((COUNTER++))

다음 은 bash Shell 학습 , 3rd Edition, pp. 147, 148 에서 발췌 한 것입니다 .

bash 산술 표현식은 Java 및 C 언어의 해당 표현식과 동일합니다. [9] 우선 순위와 연관성은 C에서와 동일합니다. 표 6-2는 지원되는 산술 연산자를 보여줍니다. 이들 중 일부는 특수 문자 (또는 포함)이지만 $ ((...)) 구문 내에 있기 때문에 백 슬래시 이스케이프 할 필요가 없습니다.

..........................

++ 및-연산자는 값을 1 씩 늘리거나 줄일 때 유용합니다. [11] Java 및 C에서와 동일하게 작동합니다. 예를 들어 value ++는 값을 1 씩 증가시킵니다 . 이것을 post-increment 라고합니다 . 도있다 선행 증가 ++ : . 차이점은 예를 통해 분명해집니다.

$ i=0
$ echo $i
0
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2

참조 http://www.safaribooksonline.com/a/learning-the-bash/7572399/를


counter스크립트를 업데이트하지 않은 것 같습니다.counter++

참고 URL : https://stackoverflow.com/questions/10515964/counter-increment-in-bash-loop-not-working

반응형