1

我想从 3G 调制解调器中提取和记录各种参数,因为存在间歇性丢失。因此,我使用 wget3Ginfo.html从 3G 调制解调器读取并将内容放入文件contents.txt中。使用 Notepad++ 打开此文件会显示所有数据。

由于我的声誉,我无法发布图片,因此下面的代码是我能做的最好的;从记事本++(打开查看所有字符),我得到:

<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>
4

3 回答 3

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结尾转换为 just \n,但不会触及 Unix 文件。对于在混合 Unix/Windows 环境中工作的人来说,这是一个救命稻草。

我希望为旧的Mac风格的文本文件找到一些类似的层(在 Mac OS X 之前的日子里,Macintosh 文件只以 a 结尾,\r而根本没有\n。那将真正解决问题。不幸的是,我没有找到任何文档。很长时间以来,您没有 OS X Macintosh 之前的文本文件。

于 2013-03-01T03:52:18.807 回答
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
于 2013-03-01T02:05:08.830 回答
0

你可以 chomp() 关闭它...

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

在某些系统上,我看到需要调用 chomp() 两次,以摆脱多个行尾字符……是的,确实存在。您可能还想添加一些东西来去除所有这些 HTML 标记?请参阅:如何使用 Perl 去除字符串中的 HTML?

于 2013-03-01T03:49:35.773 回答