使用 sed 和正则表达式从字符串中提取数字

Posted

技术标签:

【中文标题】使用 sed 和正则表达式从字符串中提取数字【英文标题】:Extract numbers from a string using sed and regular expressions 【发布时间】:2012-10-19 12:17:59 【问题描述】:

sed 专家的另一个问题。

我有一个表示路径名的字符串,其中包含两个数字。一个例子是:

./pentaray_run2/Trace_220560.dat

我需要提取这些数字中的第二个 - 即 220560

我(在论坛的帮助下)能够将所有数字一起提取(即 2220560):

sed "s/[^0-9]//g"

或仅提取第一个数字:

sed -r 's|^([^.]+).*$|\1|; s|^[^0-9]*([0-9]+).*$|\1|'

但我要的是第二个数字!!非常感谢任何帮助。

PS 我后面的数字总是字符串中的第二个数字。

【问题讨论】:

【参考方案1】:

这样好吗?

sed -r 's/.*_([0-9]*)\..*/\1/g'

用你的例子:

kent$   echo "./pentaray_run2/Trace_220560.dat"|sed -r 's/.*_([0-9]*)\..*/\1/g'
220560

【讨论】:

伟大的作品是一种享受。我猜里面的 _ 意味着只在下划线之后查找数字?在这种情况下,我总是可以期待一个下划线,所以这会起作用。这是表达式的哪个实际位。* _ St​​ackoverflow 真的是一个非常棒的资源 - 我已经为此困惑了好几个小时。出于兴趣,您是否认为有一种方法可以在末尾使用 \1 - 也许将所有数字(连续数字)提取为子字符串并要求第二个。这对我和其他人将来可能有用吗?【参考方案2】:

你可以用这个提取最后的数字:

sed -e 's/.*[^0-9]\([0-9]\+\)[^0-9]*$/\1/'

倒过来想想更容易:

    从字符串末尾开始,匹配零个或多个非数字字符 匹配(并捕获)一个或多个数字字符 至少匹配一个非数字字符 将所有字符匹配到字符串的开头

比赛的第 3 部分是“魔术”发生的地方,但它也限制了您的比赛在数字前至少有一个非数字(即,您不能匹配只有一个数字的字符串字符串的开头,尽管有一个简单的解决方法是在字符串的开头插入一个非数字)。

魔法是抵消.* 从左到右的贪婪(第 4 部分)。如果没有第 3 部分,第 4 部分将消耗它所能消耗的所有内容,其中包括数字,但是有了它,匹配确保它停止,以允许至少一个非数字后跟一个数字被第 1 部分和第 2 部分消耗,允许捕获号码。

【讨论】:

【参考方案3】:

如果grep 受到欢迎:

$ echo './pentaray_run2/Trace_220560.dat' | grep -oP '\d+\D+\K\d+'
220560

Perl 使用相同的正则表达式更便携:

echo './pentaray_run2/Trace_220560.dat' | perl -lne 'print $& if /\d+\D+\K\d+/'
220560

我认为这种方法比使用 sed 更简洁、更健壮

【讨论】:

【参考方案4】:

这可能对你有用(GNU sed):

sed -r 's/([^0-9]*([0-9]*))2.*/\2/' file

这会提取第二个数字:

sed -r 's/([^0-9]*([0-9]*))1.*/\2/' file

这会提取第一个。

【讨论】:

以上是关于使用 sed 和正则表达式从字符串中提取数字的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式和 sed 提取分支名称?

使用正则表达式从字符串中提取数字和符号

从字符串中提取分数、小数和数字的正则表达式[关闭]

使用java创建正则表达式以从字符串中提取4位数字

JavaScript 正则表达式 - 从单词旁边提取数字

用于在数字之前从 csv 中提取字符串的正则表达式