我在其他地方读到了如何做到这一点,但他们让我感到困惑。
我想从文本文件中读取行,当我遇到某一行时,我想向其添加内容。
我的代码是:
open my $p, "$username_filename" or die "can not open $username_filename: $!";
foreach $line (<$p>){
if ($line =~ /^listen/){
`echo "whatever" >> $username_file`;
}
}
然而,当我运行此操作时,我收到此错误
sh: -c: line 0: syntax error near unexpected token `newline' sh: -c: line 0: `echo "current_user" >> '
编辑文件是否正确?为什么我会收到此错误?
答案 0 :(得分:6)
使用文件与在文字处理器中编辑不同。线条是幻觉,文件只是一大串字符。您无法更改文件中间的行,原因与您无法更改书中间的行相同,无法移动单词以腾出空间。
相反,就像一本书一样,如果你想改变一些东西,你需要改写整个事物。
基本算法是......
其他一些说明......
print
默认写入STDOUT,但你可以给它一个文件句柄来代替。
foreach my $line (<$fh>)
未针对文件进行优化。它会将可能很大的文件读入内存。 while(my $line = <$fh>)
一次读取一行。
我已打开strict
。这会强制您声明变量。它可以保护您免受类似于$username_file
vs $username_filename
。
您可以使用"$filename.tmp"
之类的内容,但File::Temp提供的临时文件可以保证是临时的,唯一的,并在程序退出时进行清理。
use strict;
use warnings;
use autodie; # because writing 'or die' gets old fast
use File::Temp; # provides safe temp files
my $filename = ...; # set it somehow
open my $read, "<", $filename;
my $temp = File::Temp->new;
while(my $line = <$read>) {
if( $line =~ /^listen/ ) {
chomp $line; # remove the newline
$line .= " whatever\n"; # add our content and put a newline back
}
# Write the line to the temp file
print $temp $line;
}
# Overwrite our file with the rewritten temp file
rename $temp->filename, $filename;
这是一个程序。如果您只想快速完成,可以使用-i
和-p
在命令行上执行此操作。
perl -i.bak -pe 'if( /^listen/ ) { chomp; $_ .= "whatever" }' filename
-p
表示要在文件的每一行上运行代码。该行将被放入$_
,并且将打印$_
中的任何内容。 -i
表示要编辑文件。 -i.bak
会对原始文件进行备份,以防您出错。
答案 1 :(得分:2)
您的尝试存在一些问题。最重要的是使用echo >> file
将附加到文件,而不是插入文件中的任意位置。
另一个问题是,您尝试附加到名为$username_file
的文件,并且您尚未声明或定义该变量。
我不认为perl允许您插入文件的中间。我认为你最好的选择是一次读取一行文件,并在正确的行上添加你想要的文本。将每一行写入一个新文件,然后在最后交换文件。
例如:
#!/usr/bin/perl
my $in_filename = "in.txt";
my $out_filename = "out.txt";
open (my $in, "<", $in_filename) or die;
open (my $out, ">", $out_filename) or die;
while (my $lline = <$in>)
{
chomp $lline;
if ( $lline =~ /listen/ )
{
print "$lline whatever\n";
}
else
{
print "$lline\n";
}
}
close $in;
close $out;
rename $in_filename, "$in_filename.original";
rename $out_filename, $in_filename;
我使用chomp
删除行结尾,因为<$in>
为我们提供了一行,包括行结尾,否则会混淆附加内容。
一如往常,有很多方法可以实现这一目标。我认为使用sed
可能是一个更好的选择,但你明确地问过如何在perl中这样做,所以Perl就是。