在空间

时间:2018-03-09 07:20:11

标签: regex bash awk grep

我在shell脚本中有一个解析器:

这是要从(input.txt)解析的输入文件:

input.txt:
system.switch_cpus.commit.swp_count                 0                       # Number of s/w prefetches committed
  system.switch_cpus.commit.refs                2682887                       # Number of memory references committed
  system.switch_cpus.commit.loads               1779328                       # Number of loads committed                                                                                                                                                                                                                
  system.switch_cpus.commit.membars                   0                       # Number of memory barriers committed
  system.switch_cpus.commit.branches             921830                       # Number of branches committed
  system.switch_cpus.commit.vec_insts                 0                       # Number of committed Vector instructions.
  system.switch_cpus.commit.fp_insts                  0                       # Number of committed floating point instructions.
  system.switch_cpus.commit.int_insts          10000000                       # Number of committed integer instructions.

该脚本执行以下操作:

 $ cpu1_name="system.switch_cpus"
 $ echo "$(grep "${cpu1_name}.commit.loads" ./input.txt |grep -Eo '[0-9]+')"
 correct expected output: 1779328

但是在另一个文件中变量" cpu1_name"更改为" system.switch_cpus _1 " 现在运行相同的脚本会给我2个值:

New input file:
system.switch_cpus_1.commit.swp_count               0                       # Number of s/w prefetches committed
 system.switch_cpus_1.commit.refs              2682887                       # Number of memory references committed
 system.switch_cpus_1.commit.loads             1779328                       # Number of loads committed                                                                                                                                                                                                               
 system.switch_cpus_1.commit.membars                 0                       # Number of memory barriers committed
 system.switch_cpus_1.commit.branches           921830                       # Number of branches committed
 system.switch_cpus_1.commit.vec_insts               0                       # Number of committed Vector instructions.
 system.switch_cpus_1.commit.fp_insts                0                       # Number of committed floating point instructions.   


Modified Script line:
$ cpu1_name="system.switch_cpus_1"
$ echo "$(grep "${cpu1_name}.commit.loads" ./new_input.txt |grep -Eo '[0-9]+')"
1
1779328

正如您所看到的,管道式grep正在搜索任何数字并报告额外的" 1"由于变量名称已更改。

有没有办法只选择数字的第二部分(即只有1779328)? 我知道我可以使用awk'{print $2},但这意味着要更改脚本中的很多行。所以我在想现在的脚本行是否有更简单的技巧。

提前致谢

4 个答案:

答案 0 :(得分:1)

值(您想要获得的数字)显然被空格包围。因此,您可以使用possitive-lookbehind (?<=pattern)和possitive-lookahead (?=pattern)正则表达式条件来查找周围有空格的匹配。

请注意,要使用这些条件,您需要在grep中使用-P标志。

答案 1 :(得分:1)

Awk可以一步完成所有操作(无需管道):

"clients[]"

这应该是可移植的,适用于任何POSIX awk。

实施例

awk -v x="${cpu1_name}.commit.loads" '$1==x{print $2}' input.txt

如何运作

  • $ awk -v x="${cpu1_name}.commit.loads" '$1==x{print $2}' input.txt 1779328 $ awk -v x="${cpu1_name}.commit.loads" '$1==x{print $2}' new_input.txt 1779328

    这定义了一个awk变量-v x="${cpu1_name}.commit.loads",其中包含我们正在寻找的名称。

  • x

    如果第一个字段$1==x{print $2}等于$1,则打印第二个字段x

答案 2 :(得分:1)

由于_被视为字词char,因此1w之间没有字边界。预期数字的两边都有单词边界。

因此,您需要做的就是使用带有单词边界的模式。您可以使用\b选项作为整个单词进行匹配,也可以在\<\> / grep之间选择,grep -Ewo '[0-9]+' grep -Eo '\b[0-9]+\b' grep -Eo '\<[0-9]+\>' 支持:

sed

请参阅online demo

注意,您也可以使用sed -E 's/^\s*\S+\s+(\S+).*/\1/' 从行中提取第二个非空白块:

^

请参阅此演示。

<强>详情

  • \s* - 行首
  • \S+ - 0+ whitespaces
  • \s+ - 除了空白之外的1个字符
  • (\S+) - 1+空白字符
  • \1 - 1个非空白字符(第1组,就像我们在替换模式中保留.*占位符一样)
  • {{1}} - 其余部分。

答案 3 :(得分:0)

您可以在以下位置更改grep命令:

grep -oP '(?<=\s)[0-9]+'

要在数字链之前加上空格,最好尝试:

grep -oP '(?<=\s)\d+'

或最终在grep -oP '(?<=\s)\d+(?=\s)'grep -oP '(?<=\s)[0-9]+(?=\s)'