使用sed在没有已知分隔符的情况下在行中提取多个匹配项

时间:2015-07-19 12:36:32

标签: regex sed

我有一个大文本文件,其中包含嵌入句子中的概率。我想只提取那些概率和它们之前的文本。实施例

输入:

not interesting
foo is 1 in 1,200 and test is 1 in 3.4 not interesting
something else is 1 in 2.5, things are 1 in 10
also not interesting

通缉输出:

foo is 1/1,200
and test is 1/3.4
something else is 1/2.5,
things are 1/10

到目前为止我所拥有的:

$ sed -nr ':a s|(.*) 1 in ([0-9.,]+)|\1 1/\2\n|;tx;by; :x h;ba; :y g;/^$/d; p' input

foo is 1/1,200
 and test is 1/3.4
 not interesting
something else is 1/2.5,
 things are 1/10

something else is 1/2.5,
 things are 1/10

这个漂亮的代码在匹配时重复分割行,并尝试仅在匹配时打印它。我的代码的问题似乎是在一行完成后没有清除保留空间。

一般问题是sed不能进行非贪婪匹配,我的分隔符可以是任何东西。

我想用不同语言的解决方案是可以的,但是如果在sed中可行的话,我现在有点好奇吗?

3 个答案:

答案 0 :(得分:4)

这可能适合你(GNU sed):

sed -r 's/([0-9]) in ([0-9]\S*\s*)/\1\/\2\n/;/[0-9]\/[0-9]/P;D' file

这将替换一些数字,后跟空格,后跟in后跟一个空格,后跟一个以数字开头的标记,后跟一个可能的空格,第一个数字后跟/,后跟第二个数字令牌以数字开头,后跟新行。如果以下行包含一个数字,后跟一个/`后跟一个数字,则打印它然后将其删除,如果模式空间中有任何其他内容重复。

答案 1 :(得分:4)

sed用于单个行上的简单替换,即全部。有趣的是,使用awk:

$ cat tst.awk
{
    while ( match($0,/\s*([^0-9]+)([0-9]+)[^0-9]+([0-9,.]+)/,a) ) {
        print a[1] a[2] "/" a[3]
        $0 = substr($0,RSTART+RLENGTH)
    }
}
$ awk -f tst.awk file
foo is 1/1,200
and test is 1/3.4
something else is 1/2.5,
things are 1/10

以上使用GNU awk作为match()的第3个arg和\s的{​​{1}}简写。

答案 2 :(得分:2)

是的,可以做到,虽然它不是这项工作的最佳工具。我的尝试是搜索所有number in number模式,并在每个模式后添加换行符。然后删除尾随文本(后面没有换行符),删除前导空格并打印:

sed -nr '/([0-9]+) in ([0-9,.]+)/ { s//\1\/\2\n/g; s/\n[ ]*/\n/g; s/\n[^\n]*$//; p }' file

它产生:

foo is 1/1,200
and test is 1/3.4
something else is 1/2.5,
things are 1/10