2010-10-10 58 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