我必须删除除%之前的1,2或3位数字(0-9,或10-99或100)之外的所有内容(我不想看到%,但是)从另一个命令的输出并将其管道转发到另一个命令。我知道
sed -n '/%/p'
只会显示包含%的行,但这不是我想要的。我怎样才能摆脱剩下的不需要的文本,只留下这些数字然后将它们传递给另一个命令?
答案 0 :(得分:22)
如果你没有完全依赖于sed,这正是grep -o
所做的:
grep -o '[0-9]\{1,3\}%'
答案 1 :(得分:2)
编辑:我误解了OP并发布了无效的答案。我把它改成了一个答案,我相信,它会在更一般的情况下解决问题。
对于如下文件:
$ cat input
abc
123%
123
abc%
this is 456% and nothing more
456
使用sed -n -E 's/(^|.*[^0-9])([0-9]{1,3})%.*/\2/p' input
$ sed -n -E 's/(^|.*[^0-9])([0-9]{1,3})%.*/\2/p' input
123
456
-n
标志使sed抑制线的自动输出。然后,我们使用-E
标志,这将允许我们使用扩展的正则表达式。 (在GNU sed中,标志不是-E
,而是-r
)。
现在出现了s///
命令。组(^|.*[^0-9])
匹配行的开头(^
)或以非数字字符(.*
)结尾的一系列零个或多个字符([^0-9]
)。
[0-9]\{1,3\}
只匹配一到三位数字,并且如果该组前面有(
并且后跟{{)
,则会绑定到一个组((^|.*[^0-9])
和%
组分隔符) 1}}。然后.*
匹配此模式之前和之后的所有内容。在此之后,我们使用反向引用([0-9]{1,3})
替换第二组(\2
)的所有内容。由于我们将-n
传递给sed,因此我们不会打印任何内容,但我们将p
标志传递给s///
命令。结果是如果执行替换,则打印结果行。请注意,p
是s///
的标记,不是 p
命令,因为它位于最后{{1}之后}}
答案 2 :(得分:0)
sed -e 's/[^0-9]*\([0-9]*\)%.*/\1/'
捕获组中的数字,因为模式匹配所有内容(前导和尾随.*
),所有内容都将被丢弃。
(我的模式匹配任意数字的数字,因为sed
正则表达式不支持你在perlre和其他人看到的[0-9]{1,3}
之类的便捷快捷方式,所以我选择保持简单来说明你的原则关心)
修改:修复引用并将引号.*
替换为[^0-9]*
,以避免使用贪婪的匹配消耗数字。 perlre再次更直接,你可以使用非贪婪的.?*
答案 3 :(得分:0)
这是我的镜头:
sed "/^[0-9]{1,3}%$/ bnum; d; :num s/%//"
如果该行是1-3位数字后跟%,则删除%-sign。否则,它会删除整行。因此,对于诸如
之类的输入adsf
50
52%
1
12%
test%
1234%
%%%
85%
bye
产生
52
85
答案 4 :(得分:0)
使用awk
代替sed
。
$ cat file
one two 100% three
10% four 1% five
$ awk '{
for(i=1;i<=NF;i++)
if ($i ~/%$/) { print $i+0} }
'file
100
10
1
对于每个字段,请检查最后是否有%
个符号。如果是,请打印该号码。 ($ i + 0表示转换为整数)。使用最小正则表达式。
答案 5 :(得分:0)
sed -n "/[0-9]\{1,2\}%/ s/^[^0-9]*\([0-9]\{1,2\}\)%.*/\1/p
/100%/ s/.*/100/p
"
100%将被提取,因为否则987%的种类(如果在第1位置1上过滤则为123%)也被发送到输出