[英]Text Lines are missed when reading a file Line by Line in Perl. <cr> <lf> mismatch
我想从3G调制解调器中提取并记录各种参数,因为存在间歇性的中断。 因此,我正在使用wget从3G调制解调器读取3Ginfo.html
并将内容放入文件contents.txt
。 使用记事本++打开此文件将显示所有数据。
由于我的声誉,我无法发布图片,因此下面的代码是我能做的最好的事情; 从记事本++(打开“查看所有字符”)中,我得到:
<tr>[LF]
<td class='hd'>Signal Strength:</td>[LF]
<td>[LF]
-72[CR]
 (dBm) (High)</td>[LF]
</tr>[LF]
但是,从Perl逐行读取文件时,很明显,行数少于Notepad ++报告的行数,并且数据丢失。 在这种情况下,实际的信号强度值将丢失。
这是读取文件的Perl代码:
open hLOGFILE, "<output.txt";
while (<hLOGFILE>)
{
print "Line no $. Text is $_ ";
}
这是输出(作为文本,因为我还不能发布图片):
Line no 98 Text is <tr>
Line no 99 Text is <td class='hd'>Signal Strength:</td>
Line no 100 Text is <td>
 (dBm) (High)</td>
Line no 102 Text is </tr>
显然,缺少行,并且与行终止符的<cr>
结尾有关。 我曾尝试对文件进行拖拽,但仍然缺少这些行。
除了逐字节读取然后尝试以这种方式解析文件(这不是很吸引人)之外,我找不到解决方案。
我的计划是每分钟左右提取并记录感兴趣的行。
我尝试打开指定各种编码的文件,但仍然不满意。 如果Notepad ++可以读取和显示所有数据,为什么它在Perl中不起作用。 从Windows XP命令行使用more
,它表明数据也丢失了。
当我从chrome浏览源代码时,
<tr>
<td class='hd'>Received Signal Code Power(RSCP):</td>
<td align='center'> -78 dBm</td>
</tr>
-72[CR]
行不丢失 。 您只是没有看到它。
这是因为它不是一行,因为通常不会将回车符识别为换行符。 发生的事情是您正在将其作为一行阅读:
-72[CR] (dBm) (High)</td>[LF]
并且正在发生的事情是您正在打印:
Line No. 101 is -72
然后,打印该回车符,使光标返回到行首。 然后,打印该行的其余部分。 这掩盖了您打印出的内容,因此您看到:
 (High)</td>
因为这会覆盖该行上的先前文本。
我使用VI创建具有三种不同文件格式(“ mac” =“ \\ r”,“ unix” =“ \\ n”和“ dos” =“ \\ r \\ n”)的三个不同文件,然后使用Unix cat命令将它们组合成单个混蛋文件。
这是我的程序:
use 5.12.0;
use autodie;
open my $test_fh, "<:crlf", "new_test";
local ($/); #Enable "slurp" mode
my $file = <$test_fh>; #Whole file is read in.
$file =~ s/[\r\n]+/\n/g; #Make all line endings just \n
#
# Now "rewrite" the file
#
my @file = split /\n/, $file;
for my $line (@file) {
say qq(Line: "$line");
}
打印输出:
Line: "MAC FILE"
Line: "this"
Line: "is"
Line: "a"
Line: "test of my"
Line: "program"
Line: "this"
Line: "WINDOWS FILE"
Line: "is"
Line: "a"
Line: "test of my"
Line: "program"
Line: "UNIX FILE"
Line: "this"
Line: "is"
Line: "a"
Line: "test of my"
Line: "program"
如您所见,“ MAC文件”确实显示了所有行,但“ Line:
”一词并未显示所有行。 那是因为Perl读了一大行。 我的s/\\r+/\\n/g
将其转换为多行打印,但是while
循环将其读为一行。
看看我的open
声明。 我使用三个参数来解决Perl中的一些小问题。 不错的是,您可以将图层或编码附加到文件。 例如, <:crlf
自动将Windows文件从\\r\\n
转换为\\n
,但不会涉及Unix文件。 对于在Unix / Windows混合环境中工作的人来说,这是一个救生器。
我希望为旧的Mac样式的文本文件找到一些类似的层(在Mac OS X之前的日子中,Macintosh文件仅以\\r
结尾,根本没有\\n
。这确实可以解决问题。不幸的是,我没有找不到任何文档,因为您拥有OS X Macintosh之前的文本文件已经很长时间了。
回车为\\r
。 它在perldoc perlreref中列出。 例如,可以从您的输入循环中将其从输入中删除:
while (<hLOGFILE>) {
s/\r//g;
print "Line no $. Text is $_ ";
}
备择方案
tr/\r//d; # same thing as above, really
s/[\r\n]+$//; # remove all line endings
你可以把它砍掉...
open hLOGFILE, "<output.txt";
while (<hLOGFILE>)
{
chomp();
print "Line no $. Text is $_ \n" if( $_ );
}
在某些系统上,我看到需要两次调用chomp()来摆脱多个行尾字符的情况。 您可能还想添加一些东西来去除所有这些HTML标记? 请参阅: 如何使用Perl去除字符串中的HTML?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.