完成Perl正则表达式单线程的最佳方法

时间:2010-11-10 22:55:58

标签: regex perl awk

我正在尝试使用Perl单行来从grepping svn diff中获取一些输出,因此我可以自动测试文件。我们有一个run_test.sh脚本,它可以使用前面带有'Test'作为参数的多个PHP文件。

到目前为止,我有以下成功将'Test'添加到文件名

的内容
[gjempty@gjempty-rhel4 classes]$ svn diff | grep '(revision' | perl -wpl -e 's/(.*)\/(.*)$/$1\/Test$2/'
--- commerce/TestLCart.php      (revision 104387)
--- commerce/manufacturing/TestLRoutingData.php (revision 104387)

现在我只想抓取文件/路径将其传递给我们的run_test.sh。我可以用awk完成它,如下所示,但我正在努力提高我的Perl /单线技能。那么如何修改perl单行以仅另外提取文件路径?

 svn diff | grep '(revision' | perl -wpl -e 's/(.*)\/(.*)$/$1\/Test$2/' | awk '{print $2}' | xargs run_test.sh

3 个答案:

答案 0 :(得分:4)

你只是想要文件名,所以svn st就是你想要的。您可以这样得到:(revision,而不是获得可能包含M commerce/LCart.php的大量噪音以及您想要的主线。然后你可以砍掉\S*(任意数量的非空格字符),然后是\s*(任意数量的空格字符),然后选择剩下的字符。您可以采用不同的方式进行\S*\s*,但这是获取所有案例的最简单方法。

svn st | perl -wpl -e 's|\S*\s*(.*)/(.*)$|$1/Test$2|'

(从使用s ///发送到s |||之后切换它,所以/不需要转义;好主意,Axeman。)

答案 1 :(得分:3)

你可以很容易地摆脱grepawk

svn diff | perl -wnl -e '/\(revision/ or next; m|(\S+)/(\S+)|; print "$1/Test$2";'

我将-p更改为-n。 -p表示while (<>) { <your code>; print $_; },-n相同但没有print,因为新版本有明确的print

我使用了s///模式匹配,而不是m//替换。我将分隔符更改为|以避免斜线反斜杠(导致牙签综合征的原因)。您几乎可以使用任何标点符号。

\S.类似,但仅匹配非空白字符。模式中的.*实际上匹配斜杠前后的整个行块,但新模式仅匹配文件的路径名。由于+是“贪婪的”,当路径名中有多个斜杠时,第一个($1)将获得更多字符串,与替换模式相同。

答案 2 :(得分:2)

更好的版本:

  • 无默认打印(-n
  • 首先提取子字符串
  • 替换
  • print

    perl -wnl -e '($_)=m{---\s+(\S+)} and s|/([^/]+)$|/Test$1| and print "$_\n";'
    

您现在不需要awk。并将'(revision添加到表达式

perl -wnl -e '($_)=m{---\s+(\S+)\s+\(revision} and s|/([^/]+)$|/Test$1| and print "$_\n";'

您也不需要grep

但我创建了几个颠覆工具,如果你想要的是更改的文件'svn st'更好。

svn st | perl -wnle 'm/^[CM]\s+(\S+)/and$r=rindex($1,"/")+1and print substr($1,0,$r),"Test",substr($1,$r+1),"\n"'

这次我选择了rindex + substr方法。现在,没有正则表达式回溯。

相关问题