我试图回答一个问题(后来被删除),我认为这个问题是要求提取科学记数法的文本表示。 (使用R的regex实现,需要对元字符进行双重转义,并且可以在纯PCRE或Perl模式中使用,我之间的差异我并不真正理解。)我已经解决了大部分任务但仍然似乎无法捕获捕获组中的前导减号。我似乎唯一能让它成功的方法是使用前导的开括号:
> txt <- c("this is some random text (2.22222222e-200)", "other random (3.33333e4)", "yet a third(-1.33333e-40)", 'and a fourth w/o the "e" (2.22222222-200)')
> sub("^(.+\\()([-+]{0,1}[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt)
[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
> sub("^(.+\\()([-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt)
[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
#but that seems to be "cheating" ... my failures follow:
> sub("^(.+)([-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt)
[1] "2.22222222e-200" "3.33333e4" "1.33333e-40" "2.22222222-200"
> sub("^(.+)(-?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt)
[1] "2.22222222e-200" "3.33333e4" "1.33333e-40" "2.22222222-200"
> sub("^(.+)(-*[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt)
[1] "2.22222222e-200" "3.33333e4" "1.33333e-40" "2.22222222-200"
我已经用“科学记数法正则表达式减去”等术语来搜索我的耐心程度
答案 0 :(得分:6)
你可以尝试
library(stringr)
unlist(str_extract_all(txt, '-?[0-9.]+e?[-+]?[0-9]*'))
#[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
使用基于前导括号后捕获的方法
str_extract(txt, '(?<=\\()[^)]*')
#[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
答案 1 :(得分:2)
推断是“(。+)”第一个捕获组的“贪婪”能力吞噬了第二个捕获组中可选的减号,我终止了第一个捕获组 - 否定 - 性格一流,现在已经成功了。这仍然显得笨重,希望有更优雅的东西。在搜索中看到Python代码似乎暗示有“&amp; real_number”&gt;
的正则表达式定义> sub("^(.+[^-+])([-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$)", "\\2" ,txt,perl=TRUE)
[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
在查看使用substr来提取匹配项的str_extract_all中的代码之后,我现在认为我应该为我的努力选择gregexpr-regmatches范例,而不是采用三个捕获组策略的中间选择:
> hits <- gregexpr('[-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3}', txt)
> ?regmatches
> regmatches(txt, hits)
[[1]]
[1] "2.22222222e-200"
[[2]]
[1] "3.33333e4"
[[3]]
[1] "-1.33333e-40"
[[4]]
[1] "2.22222222-200"
答案 2 :(得分:1)
这似乎有效,并且不会与IP地址匹配:
sub("^.*?([-+]?\\d+(?:\\.\\d*)*(?:[Ee]?[-+]?\\d+)?).*?$", "\\1", txt)
[1] "2.22222222e-200" "3.33333e4" "-1.33333e-40" "2.22222222-200"
奇怪的是,这并不是我开始使用的正则表达式。当尝试一个没有工作时,我想我会回去用Perl进行测试:
my @txt = (
"this is some random text (2.22222222e-200)",
"other random (3.33333e4)",
"yet a third(-1.33333e-40)" ,
'and a fourth w/o the "e" (2.22222222-200)');
map { s/^.*?[^-+]([-+]?\d+(?:\.\d*)*(?:[Ee]?[-+]?\d+)?).*?$/$1/ } @txt;
print join("\n", @txt),"\n";
看起来不错:
2.22222222e-200
3.33333e4
-1.33333e-40
2.22222222-200
所以同样的正则表达式应该适用于R,对吗?
sub("^.*?[^-+]([-+]?\\d+(?:\\.\\d*)*(?:[Ee]?[-+]?\\d+)?).*?$", "\\1", txt)
[1] "0" "4" "0" "0"
显然不是。我甚至通过在new RegExp("
... ")
的Javascript中尝试使用双引号字符串来确认它是正确的,并且它也在那里工作正常。不确定R的不同之处,但删除否定的符号字符类就可以了。