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