【问题标题】:Read specific floating point values from lines of the command output从命令输出的行中读取特定的浮点值
【发布时间】:2016-07-10 20:36:43
【问题描述】:
运行终端命令以下列形式打印输出:
一些不相关的文字
更多不相关的文字
值 A = 3.14
VALUE B = 2.71
也是不相关的文字
我需要 shell 命令(或 awk)来获取对应于 VALUE A (3.14) 和 VALUE B (2.71) 的浮点值,并根据前面的字符串将它们分配给 shell 变量。使用字符串作为标识并以这种格式提取那些特定的行是很重要的。
最好避免,但可以将命令输出临时存储在文本文件中以供处理。
【问题讨论】:
标签:
bash
shell
awk
sed
grep
【解决方案1】:
对于您提供的输入,这将满足您的要求:
$ declare $(mycommand | sed -n 's/^\([^=]*\) = /\1=/p' | tr ' ' '_')
$ echo $VALUE_A
3.14
$ echo $VALUE_B
2.71
sed 脚本将从mycommand(您的数据生成器)中挑选出任何传递给它的行,其中包含一个=,两边都有一个空格,删除这些空格并将其输出传递给tr这将用下划线替换空格。 declare 在当前 shell 中执行赋值,创建新的环境变量。
分步(使用input 中的示例数据):
$ cat input
some irrelevant text
more irrelevant text
VALUE A = 3.14
VALUE B = 2.71
also irrelevant text
$ cat input | sed -n 's/^\([^=]*\) = /\1=/p'
VALUE A=3.14
VALUE B=2.71
$ cat input | sed -n 's/^\([^=]*\) = /\1=/p' | tr ' ' '_'
VALUE_A=3.14
VALUE_B=2.71
...和declare 执行这些任务。
【解决方案2】:
没有“不相关的文字”之类的东西。例如,如果您的“不相关文本”包含 = 符号,那么某些解决方案将会中断。如果它是多行的,其他解决方案会中断,等等。如果您想获得一个强大的解决方案,您必须告诉我们更多关于“不相关文本”的信息并在示例输入/输出中使用具体示例。
话虽如此,根据您的“无关文本”要求,一种可能的解决方案是:
$ declare $( cat file | awk -F' *= *' -v OFS='=' 'NF>1{gsub(/ /,"_",$1); print}' )
$ echo "$VALUE_A"
3.14
$ echo "$VALUE_B"
2.71
另一个:
$ declare $( cat file | awk -F' *= *' -v OFS='=' 'NR>2 && NR<5{gsub(/ /,"_",$1); print}' )
将cat file 替换为您正在执行的任何命令,以生成您在问题中作为示例输入显示的输出。
使用此解决方案和任何其他解决方案,由于您没有告诉我们“不相关的文本”可以/不可以包含哪些内容,您可能会发现文本并不像您希望的那样不相关,因为它可能符合我们假设只存在于“相关”行中的模式。
【解决方案3】:
运行:
while read -r a b c d; do [ "$a" = VALUE ] && [ "$c" = = ] && declare "VALUE_$b=$d"; done < <(command)
或者,如果您更喜欢分散在多行的命令:
while read -r a b c d
do
[ "$a" = VALUE ] && [ "$c" = = ] && declare "VALUE_$b=$d"
done < <(command)
这需要 bash。
工作原理
-
while read -r a b c d; do
这会启动一个循环并从标准输入中读取数据,将其划分为单词并分配变量a、b、c、d。
-
[ "$a" = VALUE ] && [ "$c" = = ] && declare "VALUE_$b=$d"
如果 a 是 VALUE 并且 c 是等号,则创建一个名为 VALUE_$b 和值 $d 的 shell 变量。
-
done
这标志着循环的结束。
-
< <(command)
这从command 的输出向循环提供输入。
第一个< 表示应该重定向循环的输入。构造 <(...) 通过进程替换从command 的输出中提供输入。