首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Perl -将指针移动到行的开始。

Perl -将指针移动到行的开始。
EN

Stack Overflow用户
提问于 2012-10-08 01:48:11
回答 2查看 2.3K关注 0票数 0

我有两个文件。

  1. 名为input.txt的模糊文件
  2. 第二个文件名为mapping.txt,由键值对组成。

我希望在mapping.txt中查找input.txt中的每个键,并将其替换为与键对应的值。

请注意,每次成功匹配时,我都希望覆盖input.txt中的行内容。

我编写了以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#! /usr/bin/perl

use strict;
use warnings;

(my $mapping,my $input)=@ARGV;

open(MAPPING,'<',$mapping) || die("couldn't read from the file, $mapping with error: $!\n");

while(<MAPPING>)
{
    chomp $_;
    my $line=$_;
    (my $key,my $value)=split("=",$line);
    open(INPUT,'+<',$input);
    while(<INPUT>)
    {
        chomp $_;
        if(index($_,$key)!=-1)
        {
            $_=~s/\Q$key/$value/g;
            # move pointer to beginning of line
           print INPUT $_."\n";
        }
    }
    close INPUT;
}
close MAPPING;

守则简介:

  1. 以读取模式打开mapping.txt文件。
  2. 因为每一行都是一个键值对,所以它将其分为键和值。
  3. 以覆盖模式打开input.txt文件。
  4. 检查是否在当前行中找到密钥。
  5. 如果找到键,则用忽略键中任何元字符的值替换键(通过前缀\Q)
  6. 此时,文件指针将位于行尾,因为前面的语句将扫描整行以找到键并替换它。
  7. 如果我可以将文件指针移动到行的开头,那么我可以用: 打印输入$_,"\n“
  8. 但是,我试图查找查找函数,但无法找到一种为此目的使用它的方法。

完成后,代码将关闭该文件。它将从mapping.txt中选择下一个键值对,并从一开始就再次扫描输入文件,寻找匹配项并替换它们。

最重要的一点是,每次内部while循环都将在input.txt上操作,这是在上一次内while循环的迭代中修改的。这样,任何成功的查找和替换操作都将继续保存在input.txt文件中。

我该怎么做?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-10-08 02:24:34

首先,您应该使用词法文件句柄( open的三个参数形式),并且始终检查状态以确保open成功(就像您对映射文件而不是输入文件所做的那样)。

建议的解决方案在使用print之前返回到行的开始将无法工作,因为您无法更新文件的一部分,除非您的替换数据与它要替换的数据大小完全相同。在你的情况下,这通常是不正确的。

有许多解决方案,第一个也是最简单的方法是反转循环,并将映射文件的read循环放置在输入文件的read循环中。您的代码将如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use strict;
use warnings;

my ($mapping, $input) = @ARGV;

open my $infh, '<', $input or die "Unable to open '$input': $!";

while (my $line = <$input>) {

  open my $mapfh, '<', $mapping or die "Unable to open '$mapping': $!";

  while (<$mapfh>) {
    chomp;
    my ($key, $value) = split /=/;
    $line =~ s/\Q$key/$value/g;
  }
  print $line;
}

但是您的输出被发送到STDOUT,您将不得不安排将输出保存到一个文件中并适当地重命名。

这里的另一种选择是使用-I命令行选项,该选项强制文件自动重命名,并在需要时保存备份。使用裸-I将通过删除旧文件和重命名新输出来修改文件,同时给参数一个类似于-I.bak的值,通过附加.bak而不是删除旧文件来重命名旧文件。-I选项仅适用于使用空<>操作符从ARGV读取的文件,并且将内置变量$^I设置为值(或空字符串'')具有相同的效果。代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use strict;
use warnings;

my $mapping = shift @ARGV;
$^I = '.bak';

while (my $line = <>) {

  open my $mapfh, '<', $mapping or die "Unable to open '$mapping': $!";

  while (<$mapfh>) {
    chomp;
    my ($key, $value) = split /=/;
    $line =~ s/\Q$key/$value/g;
  }
  print $line;
}

第三种更简洁的选择是使用Tie::File,它将Perl数组映射到文件内容,并将数组的所有修改反映回原始文件。这就是一个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use strict;
use warnings;

use Tie::File;

my ($mapping, $input) = @ARGV;
tie my @input, 'Tie::File', $input or die "Unable to open '$input': $!";

for my $line (@input) {

  open my $mapfh, '<', $mapping or die "Unable to open '$mapping': $!";

  while (<$mapfh>) {
    chomp;
    my ($key, $value) = split /=/;
    $line =~ s/\Q$key/$value/g;
  }
}

最后,为每一行输入继续打开和读取映射文件是非常低效的,最好从其内容构建正则表达式,并在整个程序中使用它。此版本首先从映射文件构建散列%mapping,然后通过将quotemeta应用于每个散列键来转义任何regex元字符,然后将其与regex交替运算符|连接起来,从而创建regex。键按降序长度排序,以便找到最长的匹配项,并优先替换较短的匹配项。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use strict;
use warnings;

use Tie::File;

my ($mapping, $input) = @ARGV;

open my $mapfh, '<', $mapping or die "Unable to open '$mapping': $!";
my %mapping = map { chomp; /\S/ ? split /=/ : () } <$mapfh>;
my $regex = join '|', map quotemeta, sort { length $b <=> length $b } keys %mapping;

tie my @input, 'Tie::File', $input or die "Unable to open '$input': $!";

for my $line (@input) {
  $line =~ s/($regex)/$mapping{$1}/g;
}
票数 3
EN

Stack Overflow用户

发布于 2012-10-08 02:34:16

如果我可以将文件指针移动到行的开头,那么我可以用: 打印输入$_,"\n“

您的前提是错误的:假设字节序列00 01 02和规则01 = A1 A2,产生的字节序列将是00 A1 A2而不是00 A1 A2 02。解决这一问题的方法包括:

  • 使用Tie::File模块。
  • 写入另一个文件,并在完成传递后将第二个文件重命名为原始文件。这可能是最有效和可伸缩的。

seeking不是一个好主意:您将被限制为固定长度的替换,而seektell操作的是字节,而不是字符。如果您确实必须使用就地编辑,则可以使用以下循环:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
my $beginning_of_line = tell $fh;
while (<$fh>) {
  # do processing
  seek $fh, $beginning_of_line, 0;
  # do update
} continue {$beginning_of_line = tell $fh}

此外,您对输入文件进行了多次传递。假设令牌序列a b c以及规则b = d ed = f,您将根据规则的顺序生成序列a f e ca d e c!这可能不是你想要的。

另外,考虑规则a = c和输入a ba b = d之间的模糊性。这会产生c b还是d

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12779186

复制
相关文章
UIViewController初始化没有 init 导致的 Bug
话说 *** Assertion failure in UITraitCollection * _Nonnull _UIGetCurrentFallbackTraitCollection(void)(), /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3899.13.13/_UIFallbackEnvironment.m:91
韦弦zhy
2019/11/11
2.7K0
UIViewController present UIViewController 的问题
今天写了个demo才发现,当尝试在函数: func application(_ application: UIApplication, didFinishLaunchingWithOptions la
SheltonWan
2019/07/05
1.1K0
iOS架构设计:揭秘MVC, MVP, MVVM以及VIPER
你将了解到在iOS环境下如何进行系统架构设计。我们将简单回顾一些流行的框架,并通过实践一些小例子来比较它们的理论。
iOSSir
2023/03/19
1.4K0
iOS架构设计:揭秘MVC, MVP, MVVM以及VIPER
寻找协调器FindCoordinatorRequest请求流程
我们在分析消费者的时候, 有看到调用FindCoordinatorRequest的请求
石臻臻的杂货铺[同名公众号]
2022/09/28
3030
寻找协调器FindCoordinatorRequest请求流程
Kafka 核心组件之协调器
假设某 topic 有4个分区,消费者组中只有一个消费者,那么这个消费者将消费全部 partition 中的数据。
CoderJed
2018/09/13
3.1K0
Kafka 核心组件之协调器
android定时器取消,Android定时器崩溃取消
我有一个定时器运行,然后熄灭,并做了一些事情,定时器启动罚款。Android定时器崩溃取消
全栈程序员站长
2022/09/15
1.2K0
聊聊iOS中的 MVC、MVP、MVVM以及 VIPER等代码组织方式
但是现实中我们的View依然跟Model耦合,因为如果完全按照这个理想化的MVC的话,View(cell)层的设置都应该在 Controller中,这样的话,Controller会更臃肿。
進无尽
2018/09/12
4.3K0
聊聊iOS中的 MVC、MVP、MVVM以及 VIPER等代码组织方式
UIViewController生命周期
UIViewController采用懒加载的方式,也就是说第一次访问到view属性时才会加载或创建它。由于视图由视图控制器管理,所以讨论视图的加载方式时,主要讨论视图控制器的加载方式。
Helloted
2022/06/06
2K0
UIViewController生命周期
iOS 转场动画探究(二)
这篇文章是接着第一篇写的,要是有同行刚看到的话建议从前面第一篇看,这是第一篇的地址:iOS 转场动画探究(一) 接着上一篇写的内容:        上一篇iOS 转场动画探究(一)我们说到了转场要素的第四点,把那个小实例解释完,这篇还有一点我们接着总结:        Demo的下载地址这里再发一次: 这里是Demo的下载地址 5、  转场协调器协议 UIViewControllerTransitionCoordinator        可以通过需要产生动画效果的视图控制器的transitionCoord
Mr.RisingSun
2018/01/15
1.4K0
iOS 转场动画探究(二)
[干货分享]一篇可能会让你爱上MVVM与ReactiveCocoa的文章
ios122
2018/01/02
1.3K0
iOS 转场动画探究(二)
这篇文章是接着第一篇写的,要是有同行刚看到的话建议从前面第一篇看,这是第一篇的地址:iOS 转场动画探究(一)
Mr.RisingSun
2018/07/31
8680
iOS 转场动画探究(二)
iOS14开发-UIViewController
UIViewController 可以理解为 App 的界面,负责管理 UIView 中显示的内容和用户的交互,主要有以下作用:
YungFan
2021/03/02
2.4K0
【iOS】UIViewController生命周期
2》假设view在内存中,则直接载入。相反,假设不存在。则UIViewController调用loadView方法。
全栈程序员站长
2022/07/06
8040
【iOS】UIViewController生命周期
iOS NSString类型转UIViewController
NSString * path = [[NSBundle mainBundle] pathForResource:@"ViewControllers" ofType:@"plist"];
用户9758184
2022/05/18
4900
UIViewController生命周期分析
做一个实验,通过实验来分析viewController的生命周期。 和生命周期几个相关的方法 - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"FirstVC viewDidLoad"); } -(void)viewWillAppear:(BOOL)animated { [super viewWillAppear]; NSLog(@"FirstVC viewWillAppear"); } - (void)didRe
xferris
2018/06/01
7960
tensorflow中协调器 tf.train.Coordinator
TensorFlow的Session对象是支持多线程的,可以在同一个会话(Session)中创建多个线程,并行执行。在Session中的所有线程都必须能被同步终止,异常必须能被正确捕获并报告,会话终止的时候, 队列必须能被正确地关闭。TensorFlow提供了两个类来实现对Session中多线程的管理:tf.Coordinator和 tf.QueueRunner,这两个类往往一起使用。
狼啸风云
2019/07/02
1.3K0
tensorflow中协调器 tf.train.Coordinator
iOS17适配指南之UIViewController
YungFan
2023/07/09
9040
iOS17适配指南之UIViewController
VCTransitionsLibrary –自定义iOS交互式转场动画的库
本文介绍了一种用于iOS的交互式转场实现方案,通过使用UIKit Dynamics和UIKit Layout实现自定义转场效果。具体实现包括两个部分:一是交互式转场动画的实现,通过CGAffineTransformAnimation结合UIView.animateWithDuration()方法实现;二是交互式转场交互的实现,通过监听UIViewControllerTransitionCoordinator方法实现。该方案适用于界面之间的复杂转场交互场景,可以自定义转场动画和交互逻辑,实现更加顺滑、自然的界面转场效果。
ios122
2018/01/02
1.6K0
UIViewController声明周期-iOS11新增UIViewController声明周期-iOS11新增
class subViewController: UIViewController { //nib文件的初始化 override init(nibName nibNameOr
用户8893176
2021/08/09
6770
点击加载更多

相似问题

MVVM协调器和弹出UIViewController

30

UIViewController未取消初始化

10

如果协调器不在RxSwift中,那么在RxSwift + MVVM +协调器的情况下,协调器会去哪里?

35

UIViewController与UIView之间的协调

21

从堆栈中弹出时,不会取消分配ARC UIViewController

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文