在两个特定字符或字符串之间查找文本


Answers:


16

如果您有GNU grep,则可以使用其-o选项来搜索正则表达式并仅输出匹配的部分。(其他grep实现只能显示整行。)如果一行上有多个匹配项,则将它们打印在单独的行上。

grep -o '\[[0-9]*\]'

如果您只想要数字而不是括号,那会有点困难。您需要使用零宽度的断言:一个与空字符串匹配的正则表达式,但前提是该字符串位于方括号之前(或视情况而定)。零宽度断言仅在Perl语法中可用。

grep -P -o '(?<=\[)[0-9]*(?=\])'

使用sed,您需要使用关闭打印-n,并匹配整行并仅保留匹配的部分。如果一行上可能有多个匹配项,则仅打印最后一个匹配项。有关使用sed的更多详细信息,请参见提取与“ sed”匹配的正则表达式而不打印周围的字符

sed -n 's/^.*\(\[[0-9]*\]\).*/\1/p'

或者,如果您只想要数字而不是括号:

sed -n 's/^.*\[\([0-9]*\)\].*/\1/p'

没有grep -o,如果您想要简单易懂的东西,Perl是这里的首选工具。在每一行(-n)上,如果该行包含的匹配项\[[0-9]*\],则打印该匹配项($&)和换行符(-l)。

perl -l -ne '/\[[0-9]*\]/ and print $&'

如果只希望数字,请在正则表达式中加上括号以分隔组,然后仅打印该组。

perl -l -ne '/\[([0-9]*)\]/ and print $1'

PS如果只需要括号之间的一个或多个数字,请在Perl中更改[0-9]*[0-9][0-9]*[0-9]+


一切都很好,除了他想“提取方括号之间的数字”。我认为“除外[number]”表示除外[0-9]
Peter.O 2012年

1
@ Peter.OI将“ [数字]除外”理解为表示该表格行中没有其他部分。但是我编辑了答案以显示如何仅打印数字,以防万一。
吉尔(Gilles)'所以

1
这些perl正则表达式断言看起来真的很有用!在看到您同时使用向后和向前断言(甚至在grep中)后,我一直在阅读有关它们的信息(我已经关闭了可以选择一个正则表达式引擎的事实)。从现在开始,我将花更多时间来研究perl的正则表达式。谢谢……PS ..我刚刚读到man grep…… “这是高度实验性的,grep -P可能会警告未实现的功能。” ...我希望这并不意味着不稳定(?)...
Peter.O 2012年

5

您无法使用cut

  1. tr -c -d '0123456789\012'
  2. sed 's/[^0-9]*//g'
  3. awk -F'[^0-9]+' '{ print $1$2$3 }'
  4. grep -o -E '[0-9]+'

tr 是最自然的解决方案,并且运行速度可能最快,但是我认为您需要巨大的投入才能从速度上区分所有这些选项。


对于sed来说,^.*是贪婪的,并且消耗了除最后一位以外的所有数字,并且+需要\+使用posix \([0-9][0-9]*\)....在任何情况下都's/[^0-9]*//g'可以正常工作,... Thanks for the 例如tr -c`,但这不是\012多余的吗?
Peter.O 2012年

@Peter感谢您抓住这一点。我会发誓要测试sed示例。:(我把它改成你的版本关于。\012:它需要的,否则tr会吃的换行。
凯尔·琼斯

啊哈......我看到它\012(甚至\,0,1,2)。我似乎还不适应八进制。.谢谢。
Peter.O 2012年

4

如果您的意思是在非数字字符之间提取一组连续的数字,那么我认为sed并且awk是最好的(尽管grep也可以为您提供匹配的字符):

sed:您当然可以匹配数字,但是相反的做法可能很有趣,删除非数字(只要每行只有一个数字,就可以工作):

$ echo nn3334nn | sed -e 's/[^[[:digit:]]]*//g'
3344

grep:您可以匹配连续的数字

$ echo nn3334nn | grep -o '[[:digit:]]*'
3344

我不举一个例子,awk因为我没有经验。有趣的是,尽管这sed是瑞士刀,但grep它为您提供了一种更简单,更易读的方式,该方式也适用于每条输入行中的多个数字(-o仅打印输入的匹配部分,每个部分单行):

$ echo dna42dna54dna | grep -o '[[:digit:]]*'
42
54

只是作为比较,这sed相当于“每行多个”示例grep -o '[[:digit:]]*'。。。sed -nr '/[0-9]/{ s/^[^[0-9]*|[^0-9]*$//g; s/[^0-9]+/\n/g; p}'...(+1)
Peter.O 2012年

2

既然已经说过不能做到这一点cut,我将证明即使不赞成使用cut“最佳” 解决方案,也很容易产生一种至少不比其他解决方案差的解决方案。(甚至是特别好的)解决方案。应该说,任何不专门针对数字*[]*数字的解决方案都简化了假设,因此在示例中比向问询者提供的解决方案更容易失败(例如,数字*[]*,不应显示)。此解决方案至少检查括号,并且可以扩展为也检查星号(留给读者练习):

cut -f 2 -d '[' myfile.txt | cut -f 1 -d ']'

这利用了-d指定分隔符的选项。显然,您也可以通过管道将其传递到cut表达式中,而不是从文件中读取。尽管cut它可能非常快,但由于它很简单(没有正则表达式引擎),您必须至少调用两次(或花更多时间检查*),这会增加一些过程开销。该解决方案的一个真正优点是它易于阅读,尤其是对于不熟悉正则表达式构造的临时用户。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.