正则表达式匹配用于删除句点字符的某些用法

时间:2011-10-28 17:36:54

标签: regex sed fortran

我有一些Fortran 77源文件,我正在尝试将其从非标准STRUCTURERECORD语法转换为标准化的Fortran 90 TYPE语法。其中一个棘手的方面是结构成员的不同处理方式。

非标:

s.member = 1

标准

s%member = 1

因此,我需要在这些场景中捕获句点的所有用法,并用%个字符替换它们。还不错,除非您考虑可以使用句点的所有方式(数字中的小数点,include语句中的文件名,注释中的标点符号,Fortran 77关系运算符,可能还有其他)。我已经做了一些预处理来修复关系运算符以使用Fortran 90符号,我并不真正关心修改注释的语法,但我还没有想出一个很好的方法来翻译{{1}对于上述案例,请.。看起来我应该能够用sed做到这一点,但我不确定如何匹配我需要修复的实例。以下是我想到的规则:

逐行:

  • 如果该行以%开头,那么我们就不应对该行做任何事情;将它传递给输出,所以我们不会搞乱include语句中的文件名。

  • 以下字符串是没有符号等效项的运算符,因此必须保持不变:<whitespace>include

  • 否则,如果我们找到一个被2个非数字字符包围的句点(因此它不是小数点),那么它应该是我想要替换的运算符。将该期间更改为.not. .and. .or. .eqv. .neqv.

我自己不是本土的Fortran演讲者,所以这里有一些例子:

%

解决这个问题的好方法是什么?

编辑:我实际上发现了一些额外的运算符,其中包含一个没有符号等价物的点。我已经更新了上面的规则列表。

6 个答案:

答案 0 :(得分:2)

你不能用正则表达式做到这一点,并不是那么容易。

如果我必须做你必须做的事情,我可能会手工完成,除非代码库很大。如果前者适用,首先将所有[a-zA-Z0-9]。[a-zA-Z]替换为非常奇怪的东西,保证永远不会编译,如“@ WHATEVER @”,然后继续搜索所有这些参赛作品并在手动控制后手动更换。

如果代码量很大,那么你需要编写一个解析器。我建议你使用python来标记基本的fortran结构,但请记住fortran不是一种易于解析的语言。按“每个例程”工作,并尝试查找所有使用的变量名称,将它们用作过滤器。如果您遇到类似a.whatever的内容,并且您知道a位于本地或全局变量列表中,请应用更改。

答案 1 :(得分:2)

除非代码库真的是 HUUGE (并且确实非常认真地考虑到这种情况),我只需要像 Vim < / strong>(垂直选择和块选择是你的朋友)a * nd留出一个下午手动执行此操作* 。在一个下午,我的猜测是你将完成 大部分,如果不是全部 下午是很多时间。想象一下,这两个小时内你可以覆盖多少案例。

只需通过 尝试为此类内容编写解析器,将花费更长的时间。

当然,这个问题要求自己......如果所有编译器仍支持F77的代码,并且代码有效......为什么你如此热衷于改变呢?

答案 2 :(得分:2)

我不是那些精通正则表达式的人,所以我想我会尝试从另一方面解决这个问题。如果grep关键字为STRUCTURE,则会获得代码中使用的所有STRUCTURES的列表。完成后,对于每个STRUCTURE S,您只需将S.的所有实例替换为S%

这样您就不必担心.true..and..neq.及其亲属等问题。那么主要的担心是能够解析STRUCTURE声明。

答案 3 :(得分:0)

虽然正则表达式如下:

(?<!')\b([^.\s]+)(?<!\.(?:not|and|or|eqv|neqv))(?<=\D)\.(?=\D)(?!(?:not|and|or|eqv|neqv)\.)([^.\s]+)\b(?!')

替换$1%$2

完美适用于您的示例,我不建议将其与您当前的任务一起使用。它肯定不会涵盖你的所有情况。现在如果你关心80%的覆盖率或者你可以使用它的东西,但是你应该备份你的资源。由于我有一组有限的输入案例,我确信会出现正则表达式会替换它不应该的东西的情况。

祝你好运:)

答案 4 :(得分:0)

这个sed oneliner可能是一个开始

sed -r '/^\s*include/b;/^\s*! /b;G;:a;s/^(\.(not|and|or|eqv|neqv)\.)(.*\n.*)/\3\1/;ta;s/^\.([^0-9]{2,})(.*\n.*)/\2%\1/;ta;s/^(.)(.*\n.*)/\2\1/;ta;s/\n//'

答案 5 :(得分:0)

根据您的示例,我猜测保护带引号的字符串就足够了,然后用双面字母替换句点。

perl -pe '1 while s%(\x27[^\x27]+)\.([^\x27]+\x27)%$1@@::@@$2%;
    s/([a-z])\.([a-z])/$1%$2/g;
    s/@@::@@/./g' file.f

我提供这种Perl解决方案并不是因为sed不是一个足够好的工具,而是因为它避免了sed方言之间的微小但令人讨厌的差异问题。能够为单引号使用十六进制代码是一个很好的奖励。