簡體   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