我有一个脚本:
#!/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 脚本格式化新的 shell 命令以创建以“count_”开头的变量。最后,eval
将获取创建的 shell 命令并在 shell 中评估它们。