스크립트가 있습니다.
#!/bin/bash
/root/xiotech status > xiostatus.tmp
SyncCount=$(grep -c Sync xiostatus.tmp)
PauseCount=$(grep -c paused xiostatus.tmp)
CopyingCount=$(grep -c Copying xiostatus.tmp)
if [ "$SyncCount" -eq "11" ]
then echo All 11 mirrors are in sync.
else echo $PauseCount mirrors are paused and $CopyingCount mirrors are syncing.
fi
rm -f xiostatus.tmp
awk와 같은 것을 사용하여 이러한 개수를 계산하고 "변경"하는 더 우아한 방법이 있습니까? 이 경우 파일이 작아서 별 문제가 아니지만, 파일이 900MB라면 3번 탐색하는 데 추가 사이클이 많이 걸릴 것입니다.
답변1
awk
전체 스크립트를 쉽게 교체할 수 있습니다.
#!/usr/bin/awk -f
/Sync/ {SyncCount++}
/paused/ {PauseCount++}
/Copying/ {CopyingCount++}
END {
if(SyncCount == 11)
print "All 11 mirrors are in sync."
else
print (+PauseCount) " mirrors are paused and " (+CopyingCount) " mirrors are syncing."
}
변수를 숫자로 처리하도록 (+var)
강제하는 것 입니다 (따라서 변수가 설정되지 않은 경우 출력됩니다). 블록을 사용하여 모든 변수를 초기 값 으로 설정할 수도 있습니다 .awk
0
BEGIN
0
BEGIN {
SyncCount = PauseCount = CopyingCount = 0
}
파일로 저장하고 실행해 보세요 awk -f /path/to/the/script.awk xiostatus.tmp
. 임시 파일이 필요하지 않은 경우에도 이 작업을 수행할 수 있습니다 /root/xiotech status | awk -f /path/to/the/script.awk
.
스크립트에 실행 비트를 설정하면 이를 독립 실행형 실행 파일( , 또는 ) awk
로 호출할 수 있습니다 ./path/to/the/script.awk xiostatus.tmp
/root/xiotech status | /path/to/the/script.awk
답변2
계산하고 싶으신 분들은모두awk 버전인 인스턴스는 계산됩니다.많은 종류의 중복 없음같은 줄에 여러 항목이 있으면 어떻게 되나요?
고쳐 쓰다:이제 다른 용도를 포함했습니다 split(...
. 많은match( substr(...
현재 더 빠른 방법 아래에 나열된 방법보다 빠릅니다. 이 split(...
방법은 다른 방법에 비해 4배 이상 빠르다... (87개 파일, 총 407,612줄에 대해 테스트.
자세한 비교를 위해,마이클 모로젝방법, /Sync/
범위 선택 사용(이것은철사각 패턴과 개수가 포함되어 있습니다.모두스키마)는 이 새로운 방법보다 두 배 빠릅니다(동일한 데이터에 대해).
이렇게 빨라지는 또 다른 측면(?) 이점은 split(methos)
파일의 유효하지 않은 UTF-8 문자에 대해 상당히 관대하다는 것입니다(구분자 패턴이 아닌 한).구분 기호그 자체가 계산되는 실제 문자열 패턴입니다. 내 테스트 파일 중 일부에는 유효하지 않은 UTF-8이 포함되어 있었고 두 방법에서 다른 결과를 얻는 이유를 알아내는 데 오랜 시간이 걸렸습니다.
문제의 파일이 유효한 UTF-8로 다시 인코딩되면 두 방법 모두 동일한 결과를 생성합니다.
여기에 새로운 더 빠른 방법이 있습니다(4배 이상 더 빠름)... 사용split(...
#!/bin/bash
pat='xx|yy|zz'
awk -v vpat="$pat" 'BEGIN {
split(vpat, pat, "|"); for(i in pat) pz++
}
{ if (NF) { for( p in pat ) { ct[p]+=(split( $0, A, pat[p] ) -1) }}
}
END { print " count pattern"
for (p=1; p<=pz; p++) { printf "%6d %s\n", +ct[p], pat[p] }
}' file
이것이 더 느린 방법입니다. 사용match( substr(...
#!/bin/bash
# Count occurrences of multiple non-overlapping string patterns
awk 'BEGIN {
pattern[1]="xx"
pattern[2]="yy"
pattern[3]="zz"
}
{ for( p in pattern ) {
LHB=0; RSTART=RLENGTH=1
while( match( substr( $0, LHB+=(RSTART+RLENGTH-1)), pattern[p] )){
count[p]++
}
}
} END {
print "occurs pattern"
for (p in pattern) {
printf "%6d %s\n", +count[p], pattern[p]
}
}' file
입력 파일입니다
xx xx xx
xx yy xx
출력은 다음과 같습니다.
occurs pattern
5 xx
1 yy
0 zz
답변3
어때요?
eval `/root/xiotech status | grep -Eo 'Sync|paused|Copying' | sort | uniq -c |
awk '{print "count_" $2 "=" $1}'`
if [ "$count_Sync" -eq 11 ]; then
echo All 11 mirrors are in sync.
else
echo $count_paused mirrors are paused and $count_Copying mirrors are syncing.
fi
grep -Eo
여러 패턴("|"로 구분) 검색을 허용 하고 일치하는 문자열만 반환합니다. sort | uniq -c
찾은 단어 수를 표시합니다 . awk 스크립트는 "count_"로 시작하는 변수를 생성하도록 새 쉘 명령의 형식을 지정합니다. 마지막으로 eval
생성된 셸 명령은 셸에서 가져와 평가됩니다.