作为一个全新的 Linux 用户,我从未(真正)使用过sed
和awk
(或任何其他)工具来解析文本。我想从中提取
速度:1624.127424 Kib/s in 9.410000 秒
以秒为单位的时间值,就在seconds
单词之前,
我应该为此研究哪个工具?
您可以使用许多工具,但awk
都可以:
echo "Speed : 1624.127424 Kib/s in 9.410000 seconds" | awk '{print $6}'
或(如果您的数据在文件中):
awk '{print $6}' data.txt
给你
9.410000
说明:
这假设您感兴趣的值在行上的相对位置将保持不变(在这种情况下是第 6 个空格分隔的字段),相应地进行调整。
awk
将输入行拆分为基于空格的字段。您感兴趣的字段是第 6 个字段,因此您使用$6
.
或者,您也可以使用awk '{print $(NF-1)}'
打印行上的倒数第二个字段(NF
是一个 awk 变量,它知道给定行上的字段数)。这提供了更多的灵活性,因为它可以使用长度线(即字段数),只要您感兴趣的字段是倒数第二个)。
--
cut
将是另一种也可以使用的工具:
echo "Speed : 1624.127424 Kib/s in 9.410000 seconds" | cut -d' ' -f 6
在这种情况下,根据空格分隔符(由 指定-d
)分割行,我们再次对第 6 个字段 ( -f 6
) 感兴趣。
还有其他方法,但这两种方法似乎很直接,首先想到了。
或者,如果您不知道它在字符串中的确切位置,但您知道它在“秒”一词之前,则可以使用sed
. 这涉及到正则表达式,它不像计算字段那么简单,但它们可以让您从可能没有这种严格约束格式的字符串中获取数据。这是一种方式(这<<<
只是将字符串作为输入提供给命令的另一种方式):
sed -n 's/^.* \([0-9.]\+\) seconds.*$/\1/p' <<<"Speed : 1624.127424 Kib/s in 9.410000 seconds"
由于只有一行输入,-n
and/p
在这里是无关的,但它们形成了一个有用的模式:它们告诉sed
默认情况下不要打印所有行,而只打印搜索和替换成功的行。
该s/old/new/
语法执行搜索和替换,其中“旧”部分是正则表达式模式。
该模式[0-9.]\+ seconds
匹配一个或多个数字或句点,后跟一个空格和单词“秒”。在模式的一部分周围放置反斜杠括号会导致与该模式的该部分匹配的实际字符串保存在变量中以供以后使用;所以\([0-9.]\+\) seconds
捕获所需的数字。
因为我们只想打印那个值,所以我们把它放在^.*
匹配“从行首开始的所有内容”和.*$
匹配“直到行尾的所有内容”之间。这样一来,整条线都将被替换。然而,因为.*
是贪心的,如果我们把它放在模式前面,它会吃掉除我们数字的最后一位以外的所有数字,这是我们不想要的。在模式中添加数字前的空格可以防止这种情况发生。
我们用什么代替线?With \1
,它是匹配(第一对)反斜杠括号之间的模式部分的字符串。
编辑添加:
Perl 未在问题中列出,但与上述方法类似的sed
方法是:
perl -lne 'print $1 if /([0-9.]+) seconds/' <<<"Speed : 1624.127424 Kib/s in 9.410000 seconds"
只是为了完成,perl 可以在类似 awk 的模式下运行。假设您的数据在,那么data.txt
。
$ perl -lane 'print $F[5] data.txt'
9.410000
-a
打开自动拆分模式——perl 会自动将空格上的输入行拆分到 @F 数组中。
如果变量中有单个字符串,则可以使用 shell 本身。如果您知道它是第六个字段(就像@Levon 的 awk 解决方案假设的那样),您可以这样做:
set -- $variable
seconds=$6
或者如果你知道单词后面跟着单词seconds
,你可以使用字符串替换;
prefix=${variable%\ seconds*}
seconds=${prefix##*\ }
(临时变量包含空格后的任何内容,“秒”被修剪掉的原始变量。我们同样将所有内容从开头的最后一个空格修剪掉。)
不要低估外壳,它用途广泛,尽管有时有些古怪。
另外,cut
.
echo "Speed : 1624.127424 Kib/s in 9.410000 seconds" | cut -f 6 -d' '
文档(摘录):
cut
- 从每行文件中删除部分
-d, --delimiter=DELIM
使用
DELIM
而不是TAB
用于字段分隔符
-f, --fields=LIST
仅选择这些字段;还打印任何不包含分隔符的行,除非
-s
指定了该选项