繁体   English   中英

在Perl中逐行读取文件时,缺少文本行。 <cr><lf> 不匹配

[英]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]

&nbsp(dBm)&nbsp(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>

&nbsp(dBm)&nbsp(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]&nbsp(dBm)&nbsp(High)</td>[LF]

并且正在发生的事情是您正在打印:

Line No. 101 is -72

然后,打印该回车符,使光标返回到行首。 然后,打印该行的其余部分。 这掩盖了您打印出的内容,因此您看到:

&nbsp(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM