我在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}
,但这意味着要更改脚本中的很多行。所以我在想现在的脚本行是否有更简单的技巧。
提前致谢
答案 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,因此1
和w
之间没有字边界。预期数字的两边都有单词边界。
因此,您需要做的就是使用带有单词边界的模式。您可以使用\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组,就像我们在替换模式中保留.*
占位符一样)答案 3 :(得分:0)
您可以在以下位置更改grep命令:
grep -oP '(?<=\s)[0-9]+'
要在数字链之前加上空格,最好尝试:
grep -oP '(?<=\s)\d+'
或最终在grep -oP '(?<=\s)\d+(?=\s)'
或grep -oP '(?<=\s)[0-9]+(?=\s)'