2012-08-27 33 views
1

我正在尝试编写一个非常基本的shell到python转换器,并且在替换变量时遇到了一些麻烦。例如,我想:

echo $var1 $var2 $var3 
echo $var1 $var2 $var3 $var4 

成为:

print var1, var2, var3 
print var1, var2, var3, var4 

目前,就变成:

print var1, var2 var3 
print var1, var2 var3, var4 

我的正则表达式是:

$string =~ s/(\$[a-z]+[a-z0-9]*)(\s+\S+)/$1,$2/gi; 

出于某种原因,它不会将正则表达式再次应用于ma的第二部分即使设置了全局修饰符,也是如此。

非常感谢任何帮助!

回答

1

保持接近你的正则表达式,试试这个:

use strict; 
use warnings; 

my $string = '$var1 $var2 $var3 $var4$var5'; 

$string =~ s/\$([a-z][a-z0-9]*)\s*/$1, /gi; 
$string =~ s/,\s*$//; #removing trailing comma 
print $string . "\n"; 

输出:

var1, var2, var3, $var4 

或者我会简单地做到这一点,这可能会或可能不会与其他一些可能你工作的事情有。

s/\$(\w+)\s*/$1, /g 
+0

好的。虽然这个字符串会失败:'echo $ var1 $ var2 $ var3 $ var4 $ var6'。你也不需要'A-Z',因为你已经在最后使用了不敏感标志。 – Kash

+0

@卡什你是对的。我现在修好了。但是它会添加一个尾随的','以及下面的解决方案。不知道如何避免添加尾随逗号。 – Hameed

+0

好的。有没有一个在线测试器,我们可以测试Perl代码(不只是正则表达式,而是替换)?我认为我们可以捕获不同组中的最后一个变量,并尝试“$ 1,$ 2”。不知道这是否会奏效。 – Kash

0

你只需要修改你的正则表达式:

$string =~ s/\$([a-z][a-z0-9]*)(?:\s*|$)/$1, /gi; 
$string =~ s/,\s*$//; #courtesy Hameed 

非捕获组将确保变量结束要么用空间,或根本没有空间或将在年底的线。

一旦它已经匹配了的(\ S + \ S +)的正则表达式引擎已经移动通过第二可变这也将匹配像$var1 $var2 $var3 $var4$var6和输出var1, var2, var3, var4, var5, var6

0

回波。 先行断言将允许它来检查的是未来,而无需耗费字符串

$string =~ s{ 
    \$ 
    ([a-z]+[a-z0-9]*) # capture varname 
    (?=\s+\S+)   # lookahead 
} {$1,}gix ; 

注意,我既不匹配也不捕捉\ S + S +所以没有必要将它作为2 $替换字符串。而且/ x允许我将正则表达式分开并添加注释。

注 - 其他答案可能会与您正在做的事情更接近地匹配。我只是解释你的具体查询关于不匹配第二个变量。

0

就是否在该行的末尾出现的变量,

$string =~ s{\$([a-z]+[a-z0-9]*)(\s*$)?}{ defined $2 ? $1 : "$1," }ge; 

对应于$2(\s*$)?子模式的替代条件。 ?使匹配成为可选项,因此只有在该模式匹配成功时(即线上的最后一个变量 - 即使存在不可见的尾随空白),才会定义$2。对于“内部”变量,在末尾添加一个逗号。否则,只能使用变量名称。

例如

#! /usr/bin/env perl 

use strict; 
use warnings; 

while (defined(my $string = <DATA>)) { 
    $string =~ s{\$([a-z]+[a-z0-9]*)(\s*$)?}{ defined $2 ? $1 : "$1," }ge; 
    $string =~ s/\becho\b/print/g; # for demo only 
    print $string, "\n"; 
} 

__DATA__ 
echo $var1 $var2 $var3 
echo $var1 $var2 $var3 $var4 

输出:

print var1, var2, var3 
print var1, var2, var3, var4