Regex 如何用正则表达式捕获科学记数法中的减号?

Regex 如何用正则表达式捕获科学记数法中的减号?,regex,r,scientific-notation,Regex,R,Scientific Notation,我试图回答一个问题(后来被删除了),我想这是关于提取科学符号的文本表示的问题。(使用R的regex实现,需要对元字符进行双转义,并且可以在纯PCRE或Perl模式下使用,两者之间的区别我不太理解。)我已经解决了大部分任务,但似乎仍然无法捕获捕获组中的前导减号。我想让它成功的唯一方法是使用前面的开括号: > txt <- c("this is some random text (2.22222222e-200)", "other random (3.33333e4)", "yet a

我试图回答一个问题(后来被删除了),我想这是关于提取科学符号的文本表示的问题。(使用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" 
>txt sub(“^(+.+\\()([-+]{0,1}[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$),“\\2”,txt)
[1] “2.22222 E-200”“3.33333 E4”“-1.33333 E-40”“2.2222222-200”
>sub(“^(+.+\()([-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$”,“\\2”,txt)
[1] “2.22222 E-200”“3.33333 E4”“-1.33333 E-40”“2.2222222-200”
#但这似乎是“作弊”…我的失败如下:
>sub(“^(+.+)([-+]?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$”,“\\2”,txt)
[1] “2.22222 E-200”“3.33333 E4”“1.33333 E-40”“2.22222-200”
>sub(“^(+.+)(?[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$”,“\\2”,txt)
[1] “2.22222 E-200”“3.33333 E4”“1.33333 E-40”“2.22222-200”
>sub(“^(+.+)(.*[0-9][.][0-9]{1,16}[eE]*[-+]*[0-9]{0,3})(.+$”,“\\2”,txt)
[1] “2.22222 E-200”“3.33333 E4”“1.33333 E-40”“2.22222-200”
我对“科学符号正则表达式负号”这样的术语已经搜索到了我的耐心程度,

认为这是“(.+)”的“贪婪”能力第一个捕获组要吞掉第二个捕获组中可选的减号,我用一个否定字符类终止了第一个捕获组,现在成功了。这看起来仍然很笨拙,希望有更优雅的东西。在搜索中,我看到了Python代码,似乎暗示有“&实数”>

在查看了str_extract_all中使用substr提取匹配项的代码之后,我现在认为我应该选择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"
>点击?regmatches
>regmatches(文本,点击数)
[[1]]
[1] “2.2222 E-200”
[[2]]
[1] “3.33333 E4”
[[3]]
[1] “-1.33333 E-40”
[[4]]
[1] "2.22222222-200"
您可以试试

 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" 

str_extract(txt),(?这似乎有效,并且与IP地址不匹配:

sub("^.*?([-+]?\\d+(?:\\.\\d*)*(?:[Ee]?[-+]?\\d+)?).*?$", "\\1", txt)
[1] "2.22222222e-200" "3.33333e4"       "-1.33333e-40"    "2.22222222-200"
奇怪的是,这并不是我开始使用的正则表达式。当try-one不起作用时,我想我应该回去用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"

显然不是。我甚至通过在Javascript中使用
new RegExp(“
”)来验证双引号字符串是正确的
,它在那里也很好。不确定R有什么不同,但删除否定符号字符类成功了。

你能更新你的问题以清楚地显示起始输入和所需输出吗?这个问题使用R代码创建输入字符向量作为输入,我根据我称之为“作弊”的方法。我不知道这怎么可能了reproductible@TimBiegeleisen在最后三个
“1.33333 e-40”
是不同的谢谢…我现在用
str_-extract_-all
它似乎工作
unlist(str_-extract_-all(txt),-?[0-9.]+e[-+]?[0-9]*'))
我认为
stringr
现在在其他软件包中使用了该代码,但我在软件包新闻中没有看到这一点。@BondedDust似乎是这样,我得到的信息是
perl不受欢迎。请改为使用regexp
@BondedDust-From是在stringi之上构建的,它使用ICU库提供快速、正确的数据公共字符串操作的实现,即IE包,但我在安装的版本中没有提到这一点。也许这只是在GITHUB版本中(试图在MAC上编译,它出错了:代码>配置:错误:C++预处理器“/LIB/CPP”失败了健全性检查< /代码>…所以我仍然在CRAN版本上。)@BondedDust我不确定R是否使用Ville Laurikari()的TRE库版本来处理非Perl正则表达式。
sub("^.*?[^-+]([-+]?\\d+(?:\\.\\d*)*(?:[Ee]?[-+]?\\d+)?).*?$", "\\1", txt)
[1] "0" "4" "0" "0"