2013-05-01 60 views
1

我很確定我正在做一些愚蠢的事情,我提前道歉。我曾看過其他人在類似搜索中提出的單行,我喜歡他們的想法,但我不確定如何申請,因爲它不是直接交換。如果答案是不能做到的話,那很好,我會爲此編寫腳本。如何在文件內使用perl和regex/sed更改值?

問題:我有需要通過解析器發送的日誌文件,需要日期爲YYYY-MM-DD。這些文件可以這樣保存;然而,有些人更喜歡他們在YYYY/MM/DD爲他們自己的觀看,併發送給我。我可以用sed修改一個或兩個日期,並且這個工作很好。然而,當文件中有2-3年以上時,不必爲每個日期手動完成。

我的代碼(我留在原地調試命令):

use strict; 

use File::Copy; 
use Getopt::Std; 

my %ARGS =(); 
getopts('f:v', \%ARGS); 

my $file = $ARGS{f}; 

&main(); 

sub main($) 
{ 
    open (FIN, "<$file") || die ("Cannot open file"); 
    print "you opened the file\n"; 
while (<FIN>) { 
    my $line = $_; 
    if ($line =~ /(\d*)\/(\d*)\/(\d*) /i) { 
     #print "you are in the if"; 
     my $year = $1; 
     my $month = $2; 
     my $day = $3; 

     print $line; 
     print "\nyou have year $1\n"; 
     print "you have month $2\n"; 
     print "you have day $3\n"; 

     s/'($1\/$2\/$3)/$1-$2-$3'/; 

    } 
} 

close FIN; 
} 

我可以看到,正則表達式是獲得正確的價值觀爲我的變量,但原來的線沒有在文件中被替換。

問題:

1)如果這是可以在同一個文件中做或我需要它輸出到不同的文件?看其他答案,相同的文件應該沒問題。 2)是否需要以另一種方式打開文件或以某種方式設置爲寫入文件,而不是像運行sed一樣運行replace命令?我擔心失敗可能會在這個簡單的地方,我可以忽略不計。

謝謝!

+2

你在哪裏寫入文件...? – ikegami 2013-05-01 18:31:52

+2

不建議寫入您正在閱讀的同一個文件。你可以做的是寫入一個臨時文件,然後將該文件複製到原始文件中。你也可以用'-i'標誌來嘗試使用'sed',這會在原地修改文件。 – 2013-05-01 18:40:42

+0

謝謝你們倆的反饋。這證實了我在想什麼。我還沒有想出如何使它與多個日期的sed工作。 – user438596 2013-05-02 04:38:39

回答

1
perl -pi.bak -e 's|(\d{4})/(\d\d)/(\d\d)|$1-$2-$3|g;' input 

與日誌文件名稱替換輸入。備份文件input.bak將在您需要原始數據的情況下創建。

+0

謝謝!那樣做了。我可以問一下使用'|'嗎?而不是在你的'''之後'和'g'之前的'/'?這是一種風格偏好還是會修改腳本的行爲方式? – user438596 2013-05-02 04:41:05

+0

理論上這應該可以作爲shell腳本,別名或它自己獨特的.pl文件放在一起,這樣我可以更簡單地調用這個一行代碼? – user438596 2013-05-02 05:23:22

+0

'|'允許在正則表達式中使用/而不需要在它之前放置反斜槓\。特殊的標誌使它更好地作爲一個單線程而不是寫一個.pl文件,但你絕對可以在shell腳本中使用相同的單線程。 – 2013-05-02 16:52:54

3

你永遠不會寫入文件。使用sed,你會使用-i,並且你可以在Perl中完全相同。

perl -i -pe's{(\d{4})/(\d{2})/(\d{2})}{$1-$2-$3}g' file 

或者用備份:

perl -i~ -pe's{(\d{4})/(\d{2})/(\d{2})}{$1-$2-$3}g' file 

這相當於

local $^I = ''; # Or for the second: local $^I = '~'; 
while (<>) { 
    s{(\d{4})/(\d{2})/(\d{2})}{$1-$2-$3}g; 
    print; 
} 

如果你不想靠$^I,你必須複製它的行爲。

for my $qfn (@ARGV) { 
    open($fh_in, '<', $qfn) 
     or do { warn("Can't open $ARGV: $!\n"); next; }; 

    unlink($qfn) 
     or do { warn("Can't overwrite $ARGV: $!\n"); next; }; 

    open(my $fh_out, '>', $qfn) { 
     or do { warn("Can't create $ARGV: $!\n"); next; }; 

    while (<$fh_in>) { 
     s{(\d{4})/(\d{2})/(\d{2})}{$1-$2-$3}g; 
     print $fh_out $_; 
    } 
} 
+0

刪除了不正確的'/ e'。 – ikegami 2013-05-01 20:29:30

+0

甜美;感謝您提供關於如何做到這一點的信息。 – user438596 2013-05-02 14:33:42