【问题标题】:Replace last character in a large file替换大文件中的最后一个字符
【发布时间】:2020-03-31 00:53:20
【问题描述】:

我有一个程序可以从许多其他文件中提取数据以形成一个大的(~200MB)批量 SQL 插入语句

INSERT INTO ...
VALUES
('a','b',1,2,3),
('c','d',4,5,6),

不幸的是,最后一行需要以分号而不是逗号结尾。有没有办法(最好在我的 perl 程序中)只将最后一个字符从 , 变成 ;

我尝试过的事情:

1) 文件完成并关闭后:

open(DAT,">>$output") || die("Cannot Open File");
seek(DAT, 2, SEEK_END); 
print DAT ";"; 
close(DAT);

这只是在最后放置一个分号。

2) 在我的 perl 程序中调用 `perl -p -i -e 's/,$/;/g' $output`;,但这会替换每个逗号。

3) 打印最后一行时,以分号而不是逗号结尾。但是这不起作用,因为在写完该行之前我实际上并不知道它是最后一行。

4) 将整个文件复制到一个新文件中,除了最后一个字符是; 而不是,。然而,这很慢,因此并不理想。

【问题讨论】:

  • 你反对 CPAN 模块吗?
  • 不幸的是,是的。它在安装限制非常严格的外部服务器上运行。不确定哪些模块可用。不是最好的环境。

标签: perl


【解决方案1】:

如果您知道要替换的 ',' 始终是文件中的倒数第二个字节(最后一个字节是“\n”),那么您可以试试这个:

my $fsize = -s $filename;  
# print $fsize."\n";
open($FILE, "+<", $filename) or die $!; 
seek $FILE, $fsize-2, SEEK_SET; # or 0 (numeric) instead of SEEK_SET
print $FILE ";";
close $FILE;

【讨论】:

  • 效果很好,只是它发出警告Argument "SEEK_SET" isn't numeric in seek at app.pl line 55. 不过,只要它有效,我很高兴。
  • @AlexQueue 您可以将 SEEK_SET 替换为数字 0。
  • @AlexQueue 或添加 use Fcntl; 以导入该定义。或者使用 2(或 SEEK_END)和一个负数位置,那么您之前不需要捕获文件大小。
【解决方案2】:

你试过了

perl -p -i -e 's/,$/;/g' 

这将对文件中的每一行应用此替换。要只执行一次,请使用 -0 开关 slurp 文件:

perl -0777 -pi -e 's/,$/;/'

仅当最后一个字符是逗号(带有可选的尾随换行符)时才会匹配。如果您有尾随空格或其他字符,它将不起作用。

【讨论】:

  • 这在终端上很有效,但在我的 Perl 程序中却不行。不是一个大问题,但这意味着接受的答案更容易处理。
【解决方案3】:

您使用了错误的偏移量。 SEEK_END 将偏移量添加到 END 位置。所以使用“-2”作为偏移量。试试这个:

use strict;
use warnings;

open my $fh, "+<x.txt" or die;
seek $fh, -2, 2;
print $fh ";\n";
close $fh;

或者更健谈一点:

use strict;
use warnings;
use Fcntl qw(SEEK_END);

open my $fh, "+<x.txt" or die;
seek $fh, -2, SEEK_END;
print $fh ";\n";
close $fh;

【讨论】:

    猜你喜欢
    • 2019-12-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    相关资源
    最近更新 更多