2013-03-01 56 views
0

我想从3G调制解调器中提取并记录各种参数,因为有间歇性丢失。因此,我使用wget从3G调制解调器读取3Ginfo.html,并将内容放入文件contents.txt。使用Notepad ++打开此文件可显示所有数据。在Perl中逐行读取文件时,文本行被忽略。 <cr><lf>不匹配

由于我的名声,我不能发布图片,因此下面的代码是我能做的最好的;从记事本++(与查看全部人物开启),我得到:

<tr>[LF] 

<td class='hd'>Signal Strength:</td>[LF] 

<td>[LF] 

-72[CR] 

&nbsp(dBm)&nbsp(High)</td>[LF] 

</tr>[LF] 

然而,当文件被从Perl的线读线,很显然,有线条比用记事本的报道较少++和数据失踪。在这种情况下,实际信号强度值丢失。

这里是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时,它显示数据也丢失。

当我查看源代码从铬我得到的,

<tr> 
    <td class='hd'>Received Signal Code Power(RSCP):</td> 
    <td align='center'> -78 dBm</td> 
</tr> 

回答

1

-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之前的预先文本文件。

+0

真棒,谢谢。这就是问题所在 – user2121751 2013-03-01 09:58:45

0

回车\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 
+0

尼斯,这也有窍门。干杯。 – user2121751 2013-03-01 09:59:05

0

你可以的Chomp()它关闭...

open hLOGFILE, "<output.txt"; 
while (<hLOGFILE>) 
{ 
    chomp(); 
    print "Line no $. Text is $_ \n" if($_); 
} 

在某些系统中,我看到需要调用chomp()两次,以消除多行尾字符...是的确存在。你可能想添加一些东西去除所有这些HTML标签?参见:How can I strip HTML in a string using Perl?

+0

chomp()和多个chomp()在这种情况下似乎没有帮助。谢谢 – user2121751 2013-03-01 09:57:59