BASH字符串解析

BASH字符串解析,bash,shell,Bash,Shell,我需要编写一个脚本,在长字符串上执行一些魔术,并更改输出。除了一部分之外,我可以轻松地完成大部分脚本编写 如果我有一个bash脚本 data = “CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90” 我需要总是在“'Processor\u usage'=”之后出现

我需要编写一个脚本,在长字符串上执行一些魔术,并更改输出。除了一部分之外,我可以轻松地完成大部分脚本编写

如果我有一个bash脚本

data = “CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90”
我需要总是在“'Processor\u usage'=”之后出现的信息

我需要执行哪些命令才能执行

$p=34.38
$w=80
$c=90

请记住,百分比可能只是一个位数。

您可以使用sed作为示例。下面的示例将标记您所指向的字符串:

#!/bin/sh

DATA="CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90"

echo "$DATA" | sed "s@.*'Processor_usage'=\([0-9.]*\)%;\([0-9.]*\);\([0-9.]*\) .*@\1 \2 \3@" | while read p w c; do
    echo p=$p
    echo w=$w
    echo c=$c
done

例如,您可以使用sed。下面的示例将标记您所指向的字符串:

#!/bin/sh

DATA="CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90"

echo "$DATA" | sed "s@.*'Processor_usage'=\([0-9.]*\)%;\([0-9.]*\);\([0-9.]*\) .*@\1 \2 \3@" | while read p w c; do
    echo p=$p
    echo w=$w
    echo c=$c
done

如果此文本位于文件中:

data = “CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90”
此命令将获取您的需求:

IFS=';' read p w c < <(sed -n "/Processor_usage/{ s|.*'Processor_usage'=||; s| .*||; s|%||g; p; }" file)

IFS=';'如果此文本位于文件中,请阅读p w c<:

data = “CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90”
此命令将获取您的需求:

IFS=';' read p w c < <(sed -n "/Processor_usage/{ s|.*'Processor_usage'=||; s| .*||; s|%||g; p; }" file)
IFS=';'阅读p w c
read p w c < <(grep -oP "(?<='Processor_usage'=)[^\s]+" <<< $data | tr ';' ' ')

echo -e "p=${p}\nw=${w}\nc=${c}"
p=34.38%
w=80
c=90
read p w c<这应该可以:

read p w c < <(grep -oP "(?<='Processor_usage'=)[^\s]+" <<< $data | tr ';' ' ')

echo -e "p=${p}\nw=${w}\nc=${c}"
p=34.38%
w=80
c=90

readpwc
data="CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90"
data_re="'Processor_usage'=([0-9.]+)%?;([0-9.]+)%?;([0-9.]+)%?"
if [[ $data =~ $data_re ]]; then
  p=${BASH_REMATCH[1]}
  w=${BASH_REMATCH[2]}
  c=${BASH_REMATCH[3]}
fi

Bash具有内置的正则表达式支持;绝对没有理由使用sed之类的外部工具

data="CRITICAL - mempool lsmpi_io usage is 99.99%, mempool Processor usage is 34.38% | 'Processor_usage'=34.38%;80;90 'lsmpi_io_usage'=99.99%;80;90"
data_re="'Processor_usage'=([0-9.]+)%?;([0-9.]+)%?;([0-9.]+)%?"
if [[ $data =~ $data_re ]]; then
  p=${BASH_REMATCH[1]}
  w=${BASH_REMATCH[2]}
  c=${BASH_REMATCH[3]}
fi


这真的是bash脚本还是整行都是数据本身?Bash中带有赋值的
=
周围有空格会导致语法错误。奇怪的是,为什么需要使用Bash解析nagios插件的输出?Adrian,因为插件的作者没有响应,我无法编辑它,因为它有数千行代码,不知道从哪里开始。此回复针对非常特定的路由器内存使用。我们只有4个路由器,而lsmpi_io池的使用率始终为100%,因此插件结果对于这4个路由器来说是无用的。这真的是一个bash脚本,还是整行都是数据本身?Bash中带有赋值的
=
周围有空格会导致语法错误。奇怪的是,为什么需要使用Bash解析nagios插件的输出?Adrian,因为插件的作者没有响应,我无法编辑它,因为它有数千行代码,不知道从哪里开始。此回复针对非常特定的路由器内存使用。我们只有4个路由器,lsmpi_io池的使用率始终为100%,因此插件结果对于这4个路由器来说是无用的。我想知道OP的真正含义是“记住百分比可能只是一个位数。”。这实际上可能会影响我们如何决定是否必须排除最后一个字符。不过,我认为没有必要使用数组。您可以让
读取pwc<…
p=${p%'%}
。我还担心file.txt是否会有更多数据,而不仅仅是
*处理器使用情况*
。如果是这样的话,我们应该过滤它,使其只包含一行内容,在这行内容中,单纯使用bash是不切实际的。@konsolebox是的,你说得对,当我看到你的评论时,我几乎已经完成了编辑。但是我不同意
p=${p%'%}
。子字符串看起来更简单,效果更好:)@konsolebox哦,是的,我假设
数据必须在其他地方预定义。但是如果在某些情况下,其中没有
%
,该怎么办?我想知道OP关于“记住百分比可能只是一个位数”的真正含义是什么。这实际上可能会影响我们如何决定是否必须排除最后一个字符。不过,我认为没有必要使用数组。您可以让
读取pwc<…
p=${p%'%}
。我还担心file.txt是否会有更多数据,而不仅仅是
*处理器使用情况*
。如果是这样的话,我们应该过滤它,使其只包含一行内容,在这行内容中,单纯使用bash是不切实际的。@konsolebox是的,你说得对,当我看到你的评论时,我几乎已经完成了编辑。但是我不同意
p=${p%'%}
。子字符串看起来更简单,效果更好:)@konsolebox哦,是的,我假设
数据
必须在其他地方预定义。但是如果在某些情况下其中没有
%
,会怎么样?BASH_REMATCH的有趣用法。如果Bash的版本是4.0或更高版本,则应该很有用。尽管OP.Sed要求删除“%”符号,但如果数据是多行文件的一部分,则实际上应该使用该符号。此外,为了兼容性,参数替换和
read
将是更好的选择。@konsolebox更新为修剪
%
字符
BASH\u REMATCH
在BASH 3.x中可用,并且这种特殊的使用模式一直支持到3.0,因此这不是特定于4.x的。只是
=~
的实现因版本而异。至少4.0+已经变得更加稳定了。在早期版本中执行
[[A=~(A)]]
会导致语法错误,而引用的模式(如“'”)本应是文本字符串,但会被解释为正则表达式。也许将模式存储在变量上可以修复它,但由于这一要求,我发现扩展模式更好,而且永远不会真正依赖=~除非它适用于4.0+。实际上,我认为BASH_REMATCH不起作用是因为它,所以我说是4.0。@konsolebox我使用的语法是故意选择支持回3.0的。(当文本正则表达式或带引号的变量位于运算符的右侧时,3.x系列中的更改会影响行为——但一路返回到未带引号的参数扩展)。BASH_REMATCH的有趣用法。如果Bash的版本是4.0或更高版本,则应该很有用。尽管OP.Sed要求删除“%”符号,但如果数据是多行文件的一部分,则实际上应该使用该符号。此外,为了兼容性,参数替换和
read
将是更好的选择。@konsolebox更新为修剪
%
字符
BASH_REMATCH
在BASH 3.x中可用,并且这种特殊的使用模式一直支持到3.0,因此这不是特定于4.x的