Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何重构正则表达式匹配部分_Regex_Perl - Fatal编程技术网

Regex 如何重构正则表达式匹配部分

Regex 如何重构正则表达式匹配部分,regex,perl,Regex,Perl,例如,我在文本中简化了一些数学公式 This is ${\text{BaFe}}_{2}{\text{As}}_{2}$ crystal 我想把它转换成 This is BaFe2As2 crystal 也就是说,仅连接最内侧括号内的内容 我发现我可以使用正则表达式模式 \{[^\{\}]*\} 以匹配最里面的支架。但问题是如何将它们连接在一起 我不知道这是否可以用notepad++正则表达式替换。如果notepad++无法使用,我也可以接受perl一行程序解决方案。在notepad++中

例如,我在文本中简化了一些数学公式

This is ${\text{BaFe}}_{2}{\text{As}}_{2}$ crystal
我想把它转换成

This is BaFe2As2 crystal
也就是说,仅连接最内侧括号内的内容

我发现我可以使用正则表达式模式

\{[^\{\}]*\}
以匹配最里面的支架。但问题是如何将它们连接在一起


我不知道这是否可以用notepad++正则表达式替换。如果notepad++无法使用,我也可以接受perl一行程序解决方案。

在notepad++中使用此正则表达式。我试着匹配最里面的花括号中不存在的所有内容,然后用空白字符串替换匹配内容

[^{}]*\{|\}[^{}]*
说明:

[^{}]*\{-匹配0+个既不是{也不是}后跟{ |-或 \}[^{}]*-matches}后跟0+个既不是{也不是}的字符 更换前:

更换后:

更新:

尝试此更新的正则表达式:

\$?(?=[^$]*\$[^$]*$)(?:[^{}]*{|}[^{}]*)(?=[^$]*\$[^$]*$)\$?

文档中两个$s之间的标记可能有多个这样的等式。因此,虽然需要在所有{}之间组合文本,但也需要将其约束在$pair内。然后所有这些方程都需要处理

在单个模式中匹配它会产生一个复杂的正则表达式。相反,我们可以首先提取一对$s中的所有内容,然后从中收集{}s中的文本,从而大大简化正则表达式。这使得每一个方程都要经过两次,但是一个Latex文档对于计算来说是很小的,并且效率的损失是不会被注意到的

use warnings;
use strict;
use feature 'say';

my $text = q(This is ${\text{BaFe}}_{2}{\text{As}}_{2}$ crystal,)
         . q( and ${\text{Some}}{\mathbf{More}}$ text);

my @results;

while ($text =~ /\$(.*?)\$/g) { 
    my $eq = $1; 
    push @results, join('', $eq =~ /\{([^{}]+)\}/g);
} 

say for @results;
这会打印BaFe2As2等行

while条件中的正则表达式捕获两个$s之间的所有字符。循环体执行并再次检查条件后,正则表达式继续从上一个匹配的位置搜索字符串。这是由于全局in标量,由于它处于循环状态,所以强加在regex上。一旦不再有匹配项,循环终止

在体中,我们在{}之间进行匹配,同样由于/g,这是对方程中的所有{}进行的。然而,在这里,正则表达式位于列表上下文中,因为它被分配给一个数组,然后/g使它返回所有匹配项。它们被合并成一个字符串,并添加到数组中

为了替换已处理的方程式,请在替换中使用此选项

$text =~ s{ \$(.*?)\$ }{ join('', $1 =~ /\{([^{}]+)\}/g) }egx;
其中,修饰符e使替换部分作为Perl代码进行计算,并将结果用于替换匹配的部分。然后在其中,我们可以运行正则表达式来匹配所有{}的内容,并将其连接到字符串中,如上所述。我使用s{}{}分隔符和x修饰符,以便也能够在匹配部分中分隔事物

因为整个替换都有g修饰符,所以正则表达式会继续遍历$text,只要有方程要匹配,就用替换部分中计算的值替换它们

为了便于演示,我使用了从问题扩展而来的硬编码字符串。实际上,您将一个文件读入一个标量变量,然后对其进行处理

这取决于问题的前提,即等式中的感兴趣文本完全在{}之间

错过了寻找一个班轮的部分

perl -0777 -wnE'say join("", $1=~/\{([^{}]+)\}/g) while /\$(.*?)\$/g' file.tex
使用-0777,文件将被整个slurped读取,并且as-n在$变量中的输入行上提供一个循环;while条件中的正则表达式默认在$\上工作。在while的每次迭代中,捕获的等式的内容(单位为$1)直接匹配{}s

然后替换每个方程并打印出整个处理过的文件

perl -0777 -wne's{\$(.*?)\$}{join "", $1=~/\{([^{}]+)\}/g}eg; print' file.tex

在这里,我删除了连接上的多余空格和不必要的paren。

我假设文档中有多个空格和不必要的paren。它们是否都是单个$s之间的内联方程式(如图所示),还是也有显示的方程式?@zdim它们都是内联方程式如果您可以使用Sublime,您可以试试吗?:\$?=[^$]+\$\G\A{?>{[^{}]+}{124;[^{}]+}?R*}\$?并替换为第一个捕获组$1相当不错!向上投票。然而,我发现你的方法与我的意图相反。实际上,我必须在文本中处理乳胶配方。例如,将这是${\text{BaFe}}{2}{\text{As}}}{2}$晶体更改为这是BaFe2As2晶体。这是我的错,我将更新我的帖子。@user15964我添加了一个更新,应该可以完成这项工作。非常感谢!您是否尝试过notepad++中的更新版本,它似乎与notepad++不兼容test@user15964转义花括号后,它也在记事本++中工作-\$??=[^$]*\$[^$]*$[^$]*$?:[^{}]*\{^}[^{}]*?=[^$]*\$[^$]*$\$[^$]*$\$?@user15964我使用了稍微扩展的字符串作为示例。让我知道演示如何将文件读入$text是否有用。这就是你实际要做的。@user15964我没有注意到你特别想要一条一行的。添加了。@user15964很明显,我也错过了你想要替换这些等式的机会,即使你清楚地说了!。添加到脚本版本和一行程序中。所以
谢谢你的解答和详尽的解释!作为一名perl初学者,您从您的答案中学到了很多:@user15964听到这个消息真的很高兴:如果有什么遗漏或不清楚,请告诉我,我将添加/编辑。