[英]Change line in textfile using perl
I read other places on how to do this but they were confusing for me. 我在其他地方阅读了有关如何执行此操作的信息,但它们让我感到困惑。
I want to read lines from a text file and when I come across a certain line I want to append something to it. 我想从文本文件中读取行,当遇到某行时,我想向其添加一些内容。
My code is: 我的代码是:
open my $p, "$username_filename" or die "can not open $username_filename: $!";
foreach $line (<$p>){
if ($line =~ /^listen/){
`echo "whatever" >> $username_file`;
}
}
However when I run this I get this error 但是,当我运行这个我得到这个错误
sh: -c: line 0: syntax error near unexpected token `newline' sh: -c: line 0: `echo "current_user" >> '
Is this way correct to edit the file and why am I getting this error? 这样编辑文件的方法正确吗,为什么会出现此错误?
Working with files is not like editing in a word processor. 处理文件不像在文字处理器中进行编辑。 Lines are an illusion, a file is just a big string of characters.
行是一种错觉,文件只是一大串字符。 You can't change a line in the middle of a file for the same reason you can't change a line in the middle of a book, the words can't be moved around to make room.
出于相同的原因,您不能在文件的中间更改行,而在书的中间也不能更改行,单词也不能四处移动以腾出空间。
Instead, like a book, if you want to change something you need to rewrite the whole thing. 相反,就像一本书一样,如果您想更改某些内容,则需要重写整个内容。
The basic algorithm is to... 基本算法是...
Some other notes... 其他注意事项...
print
writes to STDOUT by default, but you can give it a filehandle to write to instead. 默认情况下,
print
写入STDOUT,但是您可以给它一个文件句柄来写入。
foreach my $line (<$fh>)
is unfortunately not optimized to read files. 不幸的是,
foreach my $line (<$fh>)
并未针对读取文件进行优化。 It will read the possibly enormous file into memory. 它将可能巨大的文件读入内存。
while(my $line = <$fh>)
reads one line at a time. while(my $line = <$fh>)
读取一行。
I've turned on strict
. 我已启用
strict
。 This forces you to declare your variables. 这迫使您声明变量。 It protects you from typos like the one you made of
$username_file
vs $username_filename
. 它可以保护您免受
$username_file
与$username_filename
造成的错字。
You could use something like "$filename.tmp"
but File::Temp provides temp files that are guaranteed to be temporary, unique and cleaned up when the program exits. 您可以使用
"$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;
That's inside a program. 在程序内部。 If you just want to do it quickly, you can do it on the command line with
-i
and -p
. 如果只想快速执行此操作,则可以在命令行上使用
-i
和-p
。
perl -i.bak -pe 'if( /^listen/ ) { chomp; $_ .= "whatever" }' filename
-p
says to run the code on each line of the file. -p
表示在文件的每一行上运行代码。 The line will be put into $_
and whatever is in $_
will be printed. 该行将放入
$_
并且将打印$_
任何内容。 -i
says to edit the file in place. -i
说要在适当位置编辑文件。 -i.bak
makes a backup of the original file just in case you make a mistake. -i.bak
会备份原始文件,以防万一您出错。
There are a few problems with your attempt. 您的尝试有一些问题。 The big one is that using
echo >> file
will append to the file, not insert at some arbitrary place inside the file. 最大的问题是使用
echo >> file
将追加到文件中,而不是插入文件中的任意位置。
Another problem is that you're trying to append to a file called $username_file
, and you haven't declared or defined that variable. 另一个问题是,您试图追加到名为
$username_file
的文件中,但尚未声明或定义该变量。
I don't think perl lets you insert into the middle of a file. 我认为perl不能让您插入文件的中间。 I think your best bet would be to read the file a line at a time, and on the correct line(s), append the text you want.
我认为最好的选择是一次一行地读取文件,并在正确的行上附加所需的文本。 Write each line to a new file, then swap the files around at the end.
将每一行写入一个新文件,然后最后交换文件。
For example: 例如:
#!/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;
I use chomp
to remove line endings, because <$in>
gives us a line including its line endings, wish otherwise messes up the append. 我使用
chomp
删除行尾,因为<$in>
给我们一行包括其行尾的内容,否则希望弄乱附加内容。
As always there are many ways to achieve this. 与往常一样,有很多方法可以实现这一目标。 I think using
sed
is probably a better option for this, but you specifically asked how to do it in perl, so perl it is. 我认为使用
sed
可能是一个更好的选择,但是您特别询问了如何在perl中进行操作,因此是perl。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.