2013-03-01 57 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