スクリプトがあります。
#!/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のようなものを使ってこれらの数を計算して「変更」するよりエレガントな方法はありますか?この場合、ファイルが小さくてあまり問題ではありませんが、ファイルが900 MBの場合、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/
範囲選択の使用(これはワイヤー各パターンと数が含まれています。みんなスキーマ)はこの新しい方法よりも倍速です(同じデータについて)。
このように高速化するもう1つの側面(?)の利点は、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
生成されたシェルコマンドは、シェルからインポートされ評価されます。