2010-10-10 55 views
2

巴什腳本做我的頭在我已經尋找正則表達式的分配,但並沒有真正找到答案,我明白了。如何捕獲正則表達式的結果,並在bash替換模式

我有一個目錄中的文件。我需要遍歷這些文件並檢查它們是否符合某些標準。在某個序列下的文件名需要增加序列。那些超過特定順序的人需要觸發警報。

我有僞代碼和需要幫助把它變成正確的bash語法:

#!/bin/sh 

function check_file() 
{ 
    # example file name "LOG_20101031144515_001.csv" 
    filename=$1 

    # attempt to get the sequence (ex. 001) part of file 

    # if sequence is greater than 003, then raise alert 

    # else change file name to next sequence (ex. LOG_20101031144515_002.csv) 
} 

for i in `ls -Ar`; do check_file $i; done; 

如果PHP是一種選擇,我可以做到以下幾點:

function check_file($file){ 
    //example file 'LOG_20101031144515_001.csv'; 

    $parts = explode('.',$file); 
    preg_match('/\d{3}$/', $parts[0], $matches); 
    if ($matches){ 
     $sequence = $matches[0]; 
     $seq  = intval($sequence); 

     if ($seq > 3){ 
      // do some code to fire alert (ex. email webmaster) 
     } 
     else{ 
      // rename file with new sequence 
      $new_seq = sprintf('%03d', ++$seq); 
      $new_file = str_replace("_$sequence", "_$new_seq", $file); 
      rename($file, $new_file); 
     } 
    } 
} 

所以長話短說,我希望有人可以幫助將PHP check_file函數移植到bash等價物。

謝謝

回答

3

首先,你的問題被標記爲[bash],但你的shebang是#!/bin/sh。我會假設Bash。

#!/bin/bash 
function check_file() 
{ 
    # example file name "LOG_20101031144515_001.csv" 
    filename=$1 

    # attempt to get the sequence (ex. 001) part of file 

    seq=${filename%.csv} 
    seq=${seq##*_} 

    # if sequence is greater than 003, then raise alert 

    if ((10#$seq > 3)) 
    then 
     echo "Alert!" 
    else 
     # else change file name to next sequence (ex. LOG_20101031144515_002.csv) 
     printf -v newseq "%03d" $((seq + 1)) 
     echo "${filename/$seq/$newseq}" # or you could set a variable or do a mv 
    fi 
} 
+0

感謝您的反饋意見;它看起來非常接近我想要做的事情。然而,我將代碼逐字地拷貝到一個測試文件中,它拋出了下面的關於函數的最後一個結束括號的錯誤:語法錯誤附近的意外令牌'}' – Jordan 2010-10-11 05:06:53

+0

再一次,謝謝。我超越了大括號的語法問題;該腳本缺少「fi」來關閉if塊。此外,該腳本缺少增加seq的位;我將其添加爲「seq = $((seq + 1))」。現在我被卡在最後一個回聲中的替代。在行中,echo「$ {filename %% $ seq.csv} $ newseq.csv」,$ seq不會被$ newseq所取代。而是附加「$ newseq.csv」,結果輸出爲LOG_20101031144515_001.csv002.csv,而不是LOG_20101031144515_002.csv – Jordan 2010-10-11 05:25:40

+0

成功!經過一番狩獵之後,我發現了bash替換模式,並用Dennis的代碼替換了echo線:echo「$ {filename/$ seq/$ newseq} – Jordan 2010-10-11 05:41:07

3

PHP IS的選項。如果你掌握PHP,你可以從shell運行它。 運行

php myfile.php 

並將輸出權限輸入到控制檯。如果PHP文件是可執行文件,並與

#!/path/to/php/executable 

然後開始你可以運行

./myfile.php 

我在bash編程沒有什麼大的專家,但爲了獲得符合特定的文件列表拍打你可以使用命令

ls -l | grep "pattern_unquoted" 

我建議你去爲PHP ;-)

+0

感謝您的建議。但是,我不會從命令行運行腳本。它將生活在一個cronned shell腳本中。 – Jordan 2010-10-10 00:42:49

+0

+1:如果約旦可以編程PHP而不是Bash,那麼PHP可能是前進的方向......特別是如果喬丹是將要維護腳本的人。 – Johnsyweb 2010-10-10 00:46:02

+4

@Jordan:如果你可以從命令行運行,你可以從Cron運行。 – Johnsyweb 2010-10-10 00:46:55

3

一個DIF ferent承擔的問題:

#!/bin/sh 

YOUR_MAX_SEQ=3 

find /path/to/files -maxdepth 1 -name 'LOG_*.csv' -print \ 
    | sed -e 's/\.csv$//' \ 
    | awk -F_ '$3 > SEQ { print }' SEQ=$YOUR_MAX_SEQ 

簡要說明:

  • 查找/path/to/files匹配的日誌中的所有文件_ *以csv
  • .csv關每一行
  • 結束使用_爲的隔板,打印線,其中所述第三字段大於$YOUR_MAX_SEQ

這將爲您提供符合條件的文件列表。或者,可以通過管道將sed輸出粘.csv回。

如果您熟悉PHP,你可能是熟悉Perl,太。

+0

嗨。謝謝你。然而它似乎沒有處理關於遞增當前序列小於3的文件序列的部分,然後用新遞增的文件名保存文件名 – Jordan 2010-10-10 01:46:46

+0

用'printf'替換'awk'中的'print'%s_% s_%03d.csv \ n「,$ 1,$ 2,$ 3 + 1}'SEQ = $ YOUR_MAX_SEQ'。 – Blrfl 2010-10-10 09:53:31

+0

糟糕...'SEQ = $ YOUR_MAX_SEQ'不屬於我最後的評論。 – Blrfl 2010-10-11 03:19:44