说我有这样的行:
*[234]*
*[23]*
*[1453]*
其中,*
代表任何字符串(形式为的字符串除外[number]
)。如何使用命令行实用程序解析这些行并提取括号之间的数字?
更一般地,它的这些工具cut
,sed
,grep
或awk
将适合这样的任务?
说我有这样的行:
*[234]*
*[23]*
*[1453]*
其中,*
代表任何字符串(形式为的字符串除外[number]
)。如何使用命令行实用程序解析这些行并提取括号之间的数字?
更一般地,它的这些工具cut
,sed
,grep
或awk
将适合这样的任务?
Answers:
如果您有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]+
。
perl
正则表达式断言看起来真的很有用!在看到您同时使用向后和向前断言(甚至在grep中)后,我一直在阅读有关它们的信息(我已经关闭了可以选择一个正则表达式引擎的事实)。从现在开始,我将花更多时间来研究perl的正则表达式。谢谢……PS ..我刚刚读到man grep
…… “这是高度实验性的,grep -P可能会警告未实现的功能。” ...我希望这并不意味着不稳定(?)...
您无法使用cut
。
tr -c -d '0123456789\012'
sed 's/[^0-9]*//g'
awk -F'[^0-9]+' '{ print $1$2$3 }'
grep -o -E '[0-9]+'
tr
是最自然的解决方案,并且运行速度可能最快,但是我认为您需要巨大的投入才能从速度上区分所有这些选项。
^.*
是贪婪的,并且消耗了除最后一位以外的所有数字,并且+
需要\+
使用posix \([0-9][0-9]*\)
....在任何情况下都's/[^0-9]*//g'
可以正常工作,... Thanks for the
例如tr -c`,但这不是\012
多余的吗?
\012
:它需要的,否则tr
会吃的换行。
\0
,1
,2
(甚至\,0,1,2)。我似乎还不适应八进制。.谢谢。
如果您的意思是在非数字字符之间提取一组连续的数字,那么我认为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)
既然已经说过不能做到这一点cut
,我将证明即使不赞成使用cut
“最佳” 解决方案,也很容易产生一种至少不比其他解决方案差的解决方案。(甚至是特别好的)解决方案。应该说,任何不专门针对数字*[
和]*
数字的解决方案都简化了假设,因此在示例中比向问询者提供的解决方案更容易失败(例如,数字*[
和]*
,不应显示)。此解决方案至少检查括号,并且可以扩展为也检查星号(留给读者练习):
cut -f 2 -d '[' myfile.txt | cut -f 1 -d ']'
这利用了-d
指定分隔符的选项。显然,您也可以通过管道将其传递到cut
表达式中,而不是从文件中读取。尽管cut
它可能非常快,但由于它很简单(没有正则表达式引擎),您必须至少调用两次(或花更多时间检查*
),这会增加一些过程开销。该解决方案的一个真正优点是它易于阅读,尤其是对于不熟悉正则表达式构造的临时用户。
[number]
”表示除外[0-9]