sed - 如何删除除定义模式之外的所有内容?

时间:2011-08-20 02:43:37

标签: sed

我必须删除除之前的1,2或3位数字(0-9,或10-99或100)之外的所有内容(我不想看到%,但是)从另一个命令的输出并将其管道转发到另一个命令。我知道

sed -n '/%/p'

只会显示包含的行,但这不是我想要的。我怎样才能摆脱剩下的不需要的文本,只留下这些数字然后将它们传递给另一个命令?

6 个答案:

答案 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///命令。结果是如果执行替换,则打印结果行。请注意,ps///标记不是 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%)也被发送到输出