Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash:在一个文件中查找模式,并为找到的每个模式应用一些代码_Bash_Shell_Unix_Awk - Fatal编程技术网

bash:在一个文件中查找模式,并为找到的每个模式应用一些代码

bash:在一个文件中查找模式,并为找到的每个模式应用一些代码,bash,shell,unix,awk,Bash,Shell,Unix,Awk,我创建了一个脚本,它将自动登录到路由器并检查当前的CPU负载,如果负载超过某个阈值,我需要它将当前的CPU值打印到标准输出 我想在脚本o/p中搜索某个模式(本例中的值80是高CPU负载的阈值),然后对于该模式的每个实例,它将检查当前值是否大于80,如果为真,它将在该模式之前打印5行,然后再打印带有该模式的当前行 问题1:如何循环模式的每个实例并分别对每个实例应用一些代码 问题2:如何在图案前打印n行,然后在图案后打印x行 例如,我使用awk搜索模式“health”,并在其后面打印6行,如下所示:

我创建了一个脚本,它将自动登录到路由器并检查当前的CPU负载,如果负载超过某个阈值,我需要它将当前的CPU值打印到标准输出

我想在脚本o/p中搜索某个模式(本例中的值80是高CPU负载的阈值),然后对于该模式的每个实例,它将检查当前值是否大于80,如果为真,它将在该模式之前打印5行,然后再打印带有该模式的当前行

问题1:如何循环模式的每个实例并分别对每个实例应用一些代码

问题2:如何在图案前打印n行,然后在图案后打印x行

例如,我使用awk搜索模式“health”,并在其后面打印6行,如下所示:

 awk '/health/{x=NR+6}(NR<=x){print}' ./logs/CpuCheck.log

提前感谢您的帮助

而不是使用awk,您可以使用
-B
-A
并切换到grep,在匹配图案之前和之后打印多行:

grep -E -B 5 -A 1 '^[0-9]+[[:space:]]+80[[:space:]]+(100|9[0-9]|8[1-9])' CpuCheck.log
该模式匹配以一些数字开头的行,后跟空格,后跟80,后跟81到100之间的较大数字。
-E
开关启用扩展正则表达式(ERE),如果要使用
+
字符表示“一个或多个”,则需要使用扩展正则表达式。如果您的grep版本不支持ERE,您可以使用稍微详细一点的
\{1,\}
语法:

grep -B 5 -A 1 '^[0-9]\{1,\}[[:space:]]\{1,\}80[[:space:]]\{1,\}\(100\|9[0-9]\|8[1-9]\)' CpuCheck.log
如果grep不是一个选项,那么另一个选择就是使用awk。最简单的方法是将所有行存储在缓冲区中:

awk 'f-->0;{a[NR]=$0}/^[0-9]+[[:space:]]+80[[:space:]]+(100|9[0-9]|8[1-9])/{for(i=NR-5;i<=NR;++i)print i, a[i];f=1}'

awk'f-->0;{a[NR]=$0}/^[0-9]+[:space:][]+80[:space:][]+(100 | 9[0-9]| 8[1-9])/{对于(i=NR-5;i而不是使用awk,您可以使用
-B
-a
并切换到grep,在模式匹配前后打印多行:

grep -E -B 5 -A 1 '^[0-9]+[[:space:]]+80[[:space:]]+(100|9[0-9]|8[1-9])' CpuCheck.log
模式匹配以一些数字开头的行,后跟空格,后跟80,后跟81到100之间的较大数字。如果要使用
+
字符表示“一个或多个”,则需要使用
-E
开关启用扩展正则表达式(ERE)。如果您的grep版本不支持ERE,您可以使用稍微详细一点的
\{1,\}
语法:

grep -B 5 -A 1 '^[0-9]\{1,\}[[:space:]]\{1,\}80[[:space:]]\{1,\}\(100\|9[0-9]\|8[1-9]\)' CpuCheck.log
如果grep不是一个选项,一种替代方法是使用awk。最简单的方法是将所有行存储在缓冲区中:

awk 'f-->0;{a[NR]=$0}/^[0-9]+[[:space:]]+80[[:space:]]+(100|9[0-9]|8[1-9])/{for(i=NR-5;i<=NR;++i)print i, a[i];f=1}'

awk'f-->0;{a[NR]=$0}/^[0-9]+[:space:]+80[:space:]+(100 | 9[0-9]| 8[1-9])/{for(i=NR-5;i不幸的是,
awk
是面向流的,没有简单的方法来获取当前行之前的行。但这并不意味着这不可能:

awk '
    BEGIN {
        bufferSize = 6;
    }
    {
        buffer[NR % bufferSize] = $0;
    }
    $2 == 80 && $3 > 80 {
        # print the five lines before the match and the line with the match
        for (i = 1; i <= bufferSize; i++) {
            print buffer[(NR + i) % bufferSize];
        }
    }
' ./logs/CpuCheck.log
awk'
开始{
缓冲区大小=6;
}
{
缓冲区[NR%bufferSize]=$0;
}
$2 == 80 && $3 > 80 {
#打印匹配前的五行和匹配的行

对于(i=1;i不幸的是,
awk
是面向流的,没有一种简单的方法来获取当前行之前的行。但这并不意味着不可能:

awk '
    BEGIN {
        bufferSize = 6;
    }
    {
        buffer[NR % bufferSize] = $0;
    }
    $2 == 80 && $3 > 80 {
        # print the five lines before the match and the line with the match
        for (i = 1; i <= bufferSize; i++) {
            print buffer[(NR + i) % bufferSize];
        }
    }
' ./logs/CpuCheck.log
awk'
开始{
缓冲区大小=6;
}
{
缓冲区[NR%bufferSize]=$0;
}
$2 == 80 && $3 > 80 {
#打印匹配前的五行和匹配的行

对于(i=1;i我认为使用awk最简单的方法是读取文件。 除了用于存储行号的内存外,它基本上应该使用0内存

如果只有一次发生

awk 'NR==FNR&&$2=="80"{to=NR+1;from=NR-5}NR!=FNR&&FNR<=to&&FNR>=from' file{,}
输出

1
2
3
4
5
6
7
8
9
10
11
12
01                   80     39     36    36    47
13
14
15
16
17
01                   80     39     36    36    47
18
19
20
8
9
10
11
12
01                   80     39     36    36    47
13
14
15
16
17
01                   80     39     36    36    47
18

工作原理 在第一个文件中,如果第二个字段设置为80,则设置为记录编号+或-或任何您想要的。 增加引用变量x

NR!=FNR
在第二个文件中

for(i in to)
每次事故

if(FNR<=to[i]&&FNR>=from[i]){print;next}

将文件作为两个参数使用两次。
{,}
扩展为
文件文件

我认为使用awk最简单的方法是读取文件。 除了用于存储行号的内存外,它基本上应该使用0内存

如果只有一次发生

awk 'NR==FNR&&$2=="80"{to=NR+1;from=NR-5}NR!=FNR&&FNR<=to&&FNR>=from' file{,}
输出

1
2
3
4
5
6
7
8
9
10
11
12
01                   80     39     36    36    47
13
14
15
16
17
01                   80     39     36    36    47
18
19
20
8
9
10
11
12
01                   80     39     36    36    47
13
14
15
16
17
01                   80     39     36    36    47
18

工作原理 在第一个文件中,如果第二个字段设置为80,则设置为记录编号+或-或任何您想要的。 增加引用变量x

NR!=FNR
在第二个文件中

for(i in to)
每次事故

if(FNR<=to[i]&&FNR>=from[i]){print;next}

将文件作为两个参数使用两次。
{,}
扩展到
文件文件

awk当然可以。另一种方法是使用
grep
-A
标志控制匹配后显示的行数和
-B
之前显示的行数。在awk中,最简单的方法是读取文件两次。在第一个循环中设置标记,然后打印betwe第二个awk中的标记当然可以做到这一点。另一种方法是使用
grep
-A
标志控制匹配后显示的行数和
-B
之前显示的行数。在awk中,最简单的方法是读取文件两次。在第一个循环中设置标记,然后在第一个循环中的标记之间打印第二个遗憾的是,我的grep版本不支持-B或-A选项。@tom你建议如何打印以下行?@TomFenech如果你也使用f,那么它将打印多行重叠行times@JID您是对的,尽管根据示例输入,这看起来不是一个问题。@A.Midany如果您的问题得到解决,d别忘了接受我的回答。谢谢幸好我的grep版本不支持-B或-A选项。@tom你建议如何打印以下行?@TomFenech如果你也使用f,那么它将打印多行重叠行times@JID您是对的,尽管根据示例输入,这看起来不是一个问题。@A.Midany如果你的问题解决了,别忘了接受我的回答。谢谢,这对我来说非常有效……我修改了阈值,以检查是否有多行符合条件