Perl的正则表达式替代哈希值

如何解决Perl的正则表达式替代哈希值

| 有没有一种有效的方法来使用Perl哈希值替换一串字符串? 例如,
$regex{foo} = \"bar\";
$regex{hello} = \"world\";
$regex{python} = \"perl\";

open(F,\"myfile.txt\");
while (<F>) {
      foreach $key (keys %regex) {
            s/$key/$regex{$key}/g;
      }
}
close(F);
有没有办法在Perl中完成上述任务?     

解决方法

        第一个问题:您确定自己所拥有的没有效率吗? 第二,最明显的下一步是将所有内容放入单个正则表达式中:
my $check = join \'|\',keys %regex;
然后您可以按以下方式进行替换:
s/($check)/$regex{$1}/g;
这仍然是“慢”的,其中键的足够重叠,而正则表达式引擎必须不断地重新检查相同的字母。您可以使用Regexp :: Optimizer之类的方法来消除重叠。但是优化的成本可能会比仅做所有事情的成本高,这取决于更改的数量(哈希中的键/值)和要修改的行数。过早的优化-! 请注意,当然,您的示例代码对替换后的文本没有任何作用。它不会就地修改文件,因此我假设您要单独处理该文件。     ,        为了证明“ 3”的要点以及出于好奇,我用OP的代码与“ 4”方法与“ 3”方法进行了一些测试。 首先,在
(token|token|...)
match表达式中塞满每个可能的标记似乎没有什么价值。 Perl需要一次检查所有令牌-与一次简单地检查每个令牌并用硬编码值进行替换相比,这有多有效,这是有争议的。 其次,执行“ 4”表示在每次匹配中都提取哈希映射键。 无论如何,这是一些数字(在草莓5.12上运行,带有4万行10万行的文件):
$regex{$1}
方法需要6秒(用/ go代替/ g需要5秒)
tie
方法需要10秒 OP方法花费不到1秒的时间(使用/ go代替/ g) “ 3”方法花费不到1秒的时间(比OP代码更快) 这是“ 3”方法:
$regex{foo} = \"bar\";
$regex{hello} = \"world\";
$regex{python} = \"perl\";
$regex{bartender} = \"barista\";

$s = <<HEADER;
\\$start = time;
open(F,\"myfile.txt\");
while (<F>) {
HEADER

foreach $key (keys %regex) {
   $s .= \"s/$key/$regex{$key}\\/go;\\n\"
}

$s .= <<FOOTER;
print \\$_;
}
close(F);
print STDERR \"Elapsed time (eval.pl): \" . (time - \\$start) . \"\\r\\n\";
FOOTER

eval $s;
    ,        定义与任何键匹配的正则表达式。
$regex = join(\"|\",map {quotemeta} keys %regex);
用match4ѭ替换match14ѭ的所有匹配项。
s/($regex)/$regex{$1}/go;
如果在程序执行期间更改
$regex
,则省略
o
修饰符。 请注意,如果存在以另一个键为前缀的键(例如
f
foo
),则在连接的正则表达式中以先到者为准(例如
f|foo
匹配
f
foo|f
匹配
foobar
中的ѭ20)。如果可能发生,您可能需要根据要赢的比赛对ѭ26进行排序。 (感谢ysth指出这一点。)     ,        
perl -e \'                                                         \\
          my %replace =  (foo=>bar,hello=>world,python=>perl);  \\
          my $find    =  join \"|\",sort keys %replace;            \\
          my $str     =  \"foo,hello,python\";                      \\
          $str        =~ s/($find)/$replace{$1}/g;                \\
          print \"$str\\n\\n\";                                       \\
        \'
您可能要考虑的事情不是逐行处理文件,而是立即处理整个文件,并在正则表达式上使用
/s
修饰符进行单行模式。     ,        开始:
#!/usr/bin/perl
use strict;
use Tie::File;

my %tr=(   \'foo\' => \'bar\',#(...)
        );
my $r =join(\"|\",map {quotemeta} keys %tr);
$r=qr|$r|;
大文件使用:
tie my @array,\"Tie::File\",$ARGV[0] || die;
for (@array) { 
    s/($r)/$tr{$1}/g;
}
untie @array;
与小文件一起使用:
open my $fh,\'<\',$ARGV[0] || die;
local $/ = undef;
my $t=<$fh>;
close $fh;
$t=~s/($r)/$tr{$1}/g;
open $fh,\'>\',$ARGV[0] || die;
print $fh $t;
close $fh;
    ,        您所拥有的按原样工作,因此不清楚您的要求是什么。 一招:您发布的代码可能会出现双重替换问题,具体取决于
%regex
和/或double33 double的内容。例如,
my %regex = (
   foo => \'bar\',bar => \'foo\',);
解决方法是将foreach移入模式,可以这么说。
my $pat =
   join \'|\',map quotemeta,# Convert text to regex patterns.
     keys %regex;

my $re = qr/$pat/;  # Precompile for efficiency.

my $qfn = \'myfile.txt\'
open(my $fh,$qfn) or die \"open: $qfn: $!\";
while (<$fh>) {
   s/($re)/$regex{$1}/g;
   ... do something with $_ ...
}
    ,        这是一个古老的问题,所以令我惊讶的是,还没有人提出这个显而易见的建议:预编译每个正则表达式(即哈希键)。
$regex{qr/foo/} = \'bar\';
$regex{qr/hello/} = \'world\';
$regex{qr/python/} = \'perl\';

open(F,\"myfile.txt\");
while (<F>) {
      foreach $key (keys %regex) {
            s/$key/$regex{$key}/g;
      }
}
close(F);
或(IMO)具有更高的可读性:
%regex = (
    qr/foo/    => \'bar\',qr/hello/  => \'world\',qr/python/ => \'perl\',);
如果您知道每条输入线只能有一个可能的匹配项,则在有很多键的情况下,成功匹配后用
last
跳过其余的正则表达式也将有所帮助。例如在
for
循环中:
s/$key/$regex{$key}/g && last;
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-