1. 任務
為了實現一些機械分詞算法,准備使用“國家語委語料庫”的分詞詞表,在線下載到得詞表文件是一個Excel文件。本文的任務就是使用Perl從該Execl文件中提取所有的詞語。
詞表文件格式如下:
需要的詞語的位置在從第8行開始的,第B列的所有單元格。一共有14629個詞語。(PS:語料庫的分詞詞表包含8萬多個詞語,但是在線下載到是出現次數在50次以上的詞語,只有這1萬多)。
2. 使用什么模塊
通過閱讀一些博文發現,PERL的Spreadsheet::ParseExcel模塊支持Excel的讀操作。
3. 如何下載模塊(windows xp上的草莓PERL)
在命令行下輸入:cpan Spreadsheet::ParseExcel,即可自動安裝。
安裝結束后,輸入perldoc Spreadsheet::ParseExcel,即可檢測是否安裝成功。(如果安裝失敗,會輸出安裝失敗)
4. 樣例代碼
感覺perldoc的樣例代碼讀起來很費力,不如直接到cpan網站上面去看樣例代碼,或者下載模塊的樣例代碼。
登錄cpan網站:http://search.cpan.org/,查找Spreadsheet::ParseExcel模塊,在其主頁
http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel-0.59/lib/Spreadsheet/ParseExcel.pm#NAME
上面可以找到樣例代碼和一些解釋。樣例代碼如下,遍歷所有的worksheet,遍歷每個worksheet下面的單元格。
use strict;
use Spreadsheet::ParseExcel;
my $parser = Spreadsheet::ParseExcel->new();
my $workbook = $parser->parse('Book1.xls');
if ( !defined $workbook ) {
die $parser->error(), ".\n";
}
for my $worksheet ( $workbook->worksheets() ) {
my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();
for my $row ( $row_min .. $row_max ) {
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet->get_cell( $row, $col );
next unless $cell;
print "Row, Col = ($row, $col)\n";
print "Value = ", $cell->value(), "\n";
print "Unformatted = ", $cell->unformatted(), "\n";
print "\n";
}
}
}
另外,在該網頁上可以找到該模塊的文件:
http://search.cpan.org/CPAN/authors/id/J/JM/JMCNAMARA/Spreadsheet-ParseExcel-0.59.tar.gz
這個壓縮包包含了很多模塊的樣例代碼。
5. 樣例文件讀取
首先建立一個只有4行1列的excel文件,進行嘗試:
然后使用前面的樣例代碼,將'Book1.xls'替換為目標文件名,即可。顯示中文亂碼。
根據網上資料來看,excel的字符編碼是unicode,一般使用如下代碼進行解決:
my $workbook = $parser->parse('example.xls', $formatter);
完整代碼如下:
use Spreadsheet::ParseExcel;
use Spreadsheet::ParseExcel::FmtUnicode;
my $parser = Spreadsheet::ParseExcel->new();
my $formatter = Spreadsheet::ParseExcel::FmtUnicode->new(Unicode_Map=>"CP936");
my $workbook = $parser->parse('example.xls', $formatter);
if ( !defined $workbook ) {
die $parser->error(), ".\n";
}
for my $worksheet ( $workbook->worksheets() ) {
my ( $row_min, $row_max ) = $worksheet->row_range();
my ( $col_min, $col_max ) = $worksheet->col_range();
for my $row ( $row_min .. $row_max ) {
for my $col ( $col_min .. $col_max ) {
my $cell = $worksheet->get_cell( $row, $col );
next unless $cell;
print "Row, Col = ($row, $col)\n";
print "Value = ", $cell->value(), "\n";
print "\n";
}
}
}
<STDIN>;
注意所有需要安裝的模塊有如下幾個:
Spreadsheet::ParseExcel:最開始安裝的。
Unicode::Map:這個要安裝一下,用於字符編碼。
IO-stringy:這個已經安裝過了,具體不清楚。
OLE-Storage_Lite:這個是訪問office套件的需要的包。在安裝Spreadsheet::ParseExcel被安裝了。
這里只需要安裝Unicode::Map即可。
上面代碼顯示結果正常:
此處可以發現,行和列的單元格的下標都是從0開始的。
6. 任務實現
詞語的行從第8行開始(下標為7),列都在第2列(下標為1)。這樣對代碼略作修改,令$row_min=7,令$col_min=$col_max=1。修改目標文件名為'CorpusWordlist.xls'。輸出結果如下:
my $worksheet_count = $workbook->worksheet_count(); #得到當前表的數量 my $filename = $workbook->get_filename(); #得到當前文件名 my $name = $worksheet->get_name(); #得到表的名稱
#----------------------------------------------------------------------寫代碼---------------------------------------------------------------------------------