[英]using perl tie::file with utf encoded file
我可以將Tie::File
與utf編碼的輸出文件一起使用嗎? 我不能讓這個工作正常。 我要做的是打開這個utf編碼文件,從文件中刪除匹配字符串並重命名該文件。
碼:
use strict;
use warnings;
use Tie::File;
use File::Copy;
my ($input_file) = qw (test.txt);
open my $infh, "<:encoding(UTF-16LE)", $input_file or die "cannot open '$input_file': $!";
for (<$infh>) {
tie my @lines, "Tie::File", $_;
shift @lines if $lines[0] =~ m/MyHeader/;
untie @lines;
my ($name) = /^(.*).csv/i;
move($_, $name . ".dat");
}
close $infh
or die "Cannot close '$input_file': $!";
代碼:(更新)
my ($input_file) = qw (test.txt);
my $qfn_in = $input_file;
my $qfn_out = $qfn_in . ".dat";
open(my $fh_in, "<:raw:perlio:encoding(UTF-16le):crlf:utf8", $qfn_in)
or die("Can't open \"$qfn_in\": $!\n");
open(my $fh_out, ">:raw:perlio:encoding(UTF-16le):crlf:utf8", $qfn_out)
or die("Can't open \"$qfn_out\": $!\n");
while (<$fh_in>) {
next if $. == 1 && /MyHeader/;
print($fh_out $_)
or die("Can't write to \"$qfn_out\": $!");
}
close($fh_in);
close($fh_out) or die("Can't write to \"$qfn_out\": $!");
rename($qfn_out, $qfn_in)
or die("Can't rename: $!\n");
這在Tie::File
perldoc中未被記錄,但是當你綁定文件時,你想要通過discipline => ':encoding(UTF-16LE)'
選項:
tie my @lines, 'Tie::File', $input_file, discipline => ':encoding(UTF-16LE)'
請注意,第三個參數是與綁定數組關聯的文件的名稱。 Tie::File
將自動打開並管理文件句柄; 沒有必要自己open
文件open
。
@lines
現在包含文件的內容,所以接下來要做的就是檢查第一行:
if ($lines[0] =~ m/pattern/) {
my $line = shift @lines;
untie @lines; # rewrites, closes the file, w/o first line
my ($name) = $line =~ /^(.*).csv/i;
rename $input_file, "$name.dat";
}
但我同意TLP的看法, Tie::File
對於這項工作來說太過分了。
(我之前的回答是關於使用正確的編碼打開文件句柄並將glob作為第三個arg傳遞給Tie::File
將不起作用,因為(1)它沒有以讀/寫模式打開文件和(2)即使它確實如此, Tie::File
也不能或不會對讀取和寫入文件句柄應用編碼)
這條線:
tie my @lines, "Tie::File", $_;
嘗試將@lines
到一個文件,其中包含每行test.txt
的名稱。 由於它似乎不是一個帶有文件名的文件,我懷疑那個tie
失敗了。
你可能會在test.txt
上使用Tie::File
。 如果您只想檢查該文件的第一行,則不需要循環。
所以你需要這樣的東西:
use autodie; #handy to check for fatal errors
tie my @lines, "Tie::File", $input_file;
shift @lines if $lines[0] =~ /MyHeader/;
untie @lines;
if ($input_file =~ /(.+).csv/i) {
move($input_file, $1);
}
但是有更簡單的方法來檢查文件的第一行。 這將檢查一個文件:
perl -we '$_=<>; print if /MyHeader/; print <>;' test.txt > test.dat
my $qfn_in = ...;
my $qfn_out = $qfn_in . ".tmp";
open(my $fh_in, "<:raw:perlio:encoding(UTF-16le):crlf:utf8", $qfn_in)
or die("Can't open \"$qfn_in\": $!\n");
open(my $fh_out, ">:raw:perlio:encoding(UTF-16le):crlf:utf8", $qfn_out)
or die("Can't open \"$qfn_out\": $!\n");
while (<$fh_in>) {
next if $. == 1 && /MyHeader/;
print($fh_out $_)
or die("Can't write to \"$qfn_out\": $!");
}
close($fh_in);
close($fh_out) or die("Can't write to \"$qfn_out\": $!");
rename($qfn_out, $qfn_in)
or die("Can't rename: $!\n");
( :perlio
和:utf8
是當時存在的bug的解決方法。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.