2015-10-02 61 views
0

我有500個文件或使凌亂的數據集的列表(的.csv)看起來像如下:正則表達式在Perl中添加小數點後的字符?

0.00, 0.53, 1.53, 0.00 0.52, 243.21 
... etc etc. 

我想:

0.00, 0.53, 1.53, 0.00, 0.52, 243.21 

用Perl(或bash),我如何匹配小數點後的所有內容,如果有空格後跟另一個號碼,那麼我會在第一個數字後插入一個逗號?

0.00 0.520.00, 0.52

我是初學者,一般以Perl和編程,所以我不太瞭解如何正確使用。 我發現正則表達式[0-9]+(\.[0-9][0-9]?)?應該工作兩位小數,但更多的小數呢?難道僅僅[0-9]+(\.[0-9]+?)?

我不成功的嘗試:

for my $file (glob '*.csv') { 
    open my $in, '<', $file;   
    my @lines; 
    while (<$in>) { 
     while(/^[0-9]+(\.[0-9]+)?$/g){ 
      print ",";  # Am I overwritting my lines here? 
     } 
     $line =~ s/,,/,/g; # Get rid of any double commas that appear now 
    } 
    close $in; 
    open my $out, '>', $file; 
    print $out $_ for @lines; 
    close $out; 
} 

我想我不能正確匹配/印刷 - 任何幫助表示讚賞,其中包括更優雅的解決方案。

預先感謝您!

回答

2

轉到用於懶:

#!/usr/bin/env perl 
use strict; 
use warnings; 

while (<DATA>) { 
    print join (", ", m/([\d\.]+)/g); 
} 

__DATA__ 
0.00, 0.53, 1.53, 0.00 0.52, 243.21 

輸出:

0.00, 0.53, 1.53, 0.00, 0.52, 243.21 

這是通過:

  • 重複匹配 「數字和點」 到一個數組
  • 然後打印該用逗號分隔。 join不會插入尾部分隔符 。

所以把你的代碼:

#!/usr/bin/env perl 
use strict; 
use warnings; 

for my $file (glob '*.csv') { 
    open my $in, '<', $file or die $!; 
    open my $out, '>', "$file.new" or die $!; 

    while (<$in>) { 
     print {$out} join (", ", m/([\d\.]+)/g); 
    } 
} 

這工作,因爲while每次循環自動的設置隱變量$_爲「當前行」。 ms默認情況下,正則表達式(以及一堆其他Perl函數)在$_上執行。

所以,你可以重寫爲:

while (my $line = <$in>) { 
    my @stuff = $line =~ m/([\d\.]+)/g; 
    print {$out} join (",", @stuff); 
} 

隱變量是一些美好的東西,但要注意他們的 - 如果他們使代碼更清晰僅使用它們。

要回答你的內聯查詢:

我在這裏overwritting我的臺詞?

否 - print ","正在寫入STDOUT。這根本不會改變你的文件。 (但是它實際上並沒有做任何有用的事情)。

您將不得不使用s模式搜索/替換$_ - 當前行 - 然後push@lines

我想你誤會了幾個基本的概念雖然這裏:

  • @lines是無關$line。您實際上沒有對@lines做任何事情,因此在您打印時它將爲空。
  • 您的whileprint循環 - 不做任何事情。 m正則表達式確實適用於$_,它被while循環隱式設置爲「當前行」。但是你沒有做任何事情來改變這個價值。
  • $line =~ ...變換$line。但$line不存在,所以沒有任何反應。

你真的應該加入use strict;use warnings你的程序的開始,因爲你會被警告這些事情。

0

我不說話perl的,但原則:

Search: (?<=\.\d\d)(?= \d) 
Replace: , 
0

如果你可以安裝領帶::文件,你可以這樣做:

use strict; 
use warnings; 
use Tie::File; 

for my $file (glob '*.csv') { 
    tie my @file, 'Tie::File', $file or die $!; 
     s/(\d)(\s+\d)/$1,$2/g foreach (@file); 
    untie @file; 
} 

注意,這將修改原始文件。 Tie :: File將文件讀入數組,並允許您修改數據。