我有一个行列表:
<some_random_text="someval" my_val_="0.4" some_random_text_1="someval_">
<some_random_text="someval" my_val_="0.8" some_random_text_1="someval_">
<some_random_text="someval" my_val_="1.2" some_random_text_1="someval_">
等等。
从每一行开始,我想返回my_val_之后给出的数值。我怎么能用bash做到这一点?
答案 0 :(得分:7)
使用grep
:
grep -oP 'my_val_="\K[^"]*' filename
-o
以便grep
仅打印匹配-P
,以便使用与Perl兼容的正则表达式。
正则表达式中的\K
从匹配中删除了前面的正则表达式部分匹配的所有内容;这具有lookbehind的效果:只有在my_val_="
之后直接匹配的非引号字符才会匹配。
答案 1 :(得分:7)
在这个非常严格的结构中,你想要做的就是使用sed非常容易:
sed 's/.*my_val_="\([0-9.]\{1,\}\)".*/\1/' file
或使用扩展正则表达式:
sed -r 's/.*my_val_="([0-9.]+)".*/\1/' file
这会捕获您感兴趣的部分(引号之间的数字和点),并使用它们来替换该行的内容。
正如评论中所提到的(感谢),启用扩展正则表达式的开关在sed版本之间有所不同。出于习惯,我倾向于使用-r
但是一些实现(例如OSX上的BSD sed)与-E
一起使用。其他人使用-r
或-E
但neither option is defined by the standard。
这个也可以在原生bash中完成(虽然我不推荐它......):
re='my_val_="([0-9.]+)"'
while read -r line; do
[[ $line =~ $re ]] && echo "${BASH_REMATCH[1]}"
done < file
=~
是正则表达式匹配运算符。捕获的数字和点存储在特殊数组1
的元素BASH_REMATCH
中。
sed和bash方法略有不同,因为sed版本将打印文件中的所有行,即使它们与模式不匹配。如果这是一个问题,您可以在命令末尾添加-n
开关和p
来打印匹配的行:
sed -nr 's/.*my_val_="([0-9.]+)".*/\1/p' file