旧版本支持Perl棘手的正则表达式转换

时间:2015-05-26 18:44:21

标签: regex perl

我正在使用正则表达式

s/^[^']*'(*SKIP)(*F)|'[^']*$(*SKIP)(*F)|(?<!\\)'/\\'/gim

成功地在最新版本的Perl中转义数据,并在Perl 5.8.8及更早版本中失败,并出现以下错误:

Returned error in Perl 5.8.8 is Quantifier follows nothing in regex; marked by <-- HERE in m/^[^']'( <-- HERE SKIP)(F)|'[^']$(SKIP)(F)|(?<!\)'/

此正则表达式获取输入数据并确保转义任何'但不是:

a)第一个'   b)最后'   c)尚未逃过一个\'

Example

如何将我的正则表达式转换为与Perl的旧版本兼容?

编辑:

输入数据:

%3 successful login (test test's test\'s string) alert for user %1 from %2|%3 successful login alert|root

输出数据:

'%3 successful login (test test\'s test\'s string) alert for user %1 from %2|%3 successful login alert|root'

而不是.... (test test\'s test\\'s string) ....

4 个答案:

答案 0 :(得分:1)

我相信你也可以使用这个在旧的perl中运行的正则表达式:

#!/usr/bin/env perl

my $string = "'%3 successful login (test test's test\'s string) alert for user's %1 from %2|%3 successful login alert|root'";

$string =~ s/^[^']*'.*?(?<!\\)\K(')(?![^']*$)|(?<!^)(?<!\\)(')(?![^']*$)/\\$1$2/gm;

print "<$string>\n";

输出:

  

<'%3 successful login (test test\'s test\'s string) alert for user\'s %1 from %2|%3 successful login alert|root'>

RegEx Demo

答案 1 :(得分:1)

my $first_idx = index($_, "'");
if ($first_idx >= 0) {
   my $last_idx  = rindex($_, "'");
   if ($last_idx != $first_idx) {
      my $length = $last_idx - $first_idx + 1;
      substr($_, $first_idx+1, $length-2) =~
         s/\G((?:[^'\\]+|\\.)*)'/$1\\'/sg;
   }
}

你可以在一个复杂的替换中完成所有操作,但除了损害可读性和可维护性之外,它可能会损害性能。

s/
   \G
   (
      (?: ^ [^']* ' | (?!^) )
      (?: [^'\\]+ | \\. )*
   )
   '
   (?! [^']* \z )
/
   $1 . "\\'"
/xseg;

测试:

var x = 'abc'def\'ghi\\'jkl\\\'mno';

变为

var x = 'abc\'def\'ghi\\\'jkl\\\'mno';

答案 2 :(得分:1)

你可能会过度思考这一点 诀窍是在需要转义之前消耗甚至先前的转义。

然后将其作为替换的一部分写回来 这总是适用于你需要逃脱的任何事情 这很简单,也是最快的方法。

 #  s/(?<!\\)((?:\\\\)*)'/$1\\'/g

 (?<! \\ )
 (                             # (1 start)
      (?: \\ \\ )*
 )                             # (1 end)
 '

我没有对外部'进行任何格式保存,但这里是
一个代码片段来抓住内脏,然后逃离内部'所在的内部 必要。将内容传递给回调(eval)以进行转义 很简单。

 use strict;
 use warnings;

 $/ = "";

 my $input = <DATA>;
 print "Input:\n$input\n";

 sub callback
 {
   my ($core) = @_;
   $core =~ s/(?<!\\)((?:\\\\)*)'/$1\\'/g;
   return "'" . $core . "'";
 }

 $input =~ s/^\s*'(.+)'\s*$/ callback( $1 );  /es;


 print "Output:\n$input\n";

 __DATA__
   '%3 successful login (test test's test\'s string) alert for user %1 from %2|%3 successful login alert|root '

答案 3 :(得分:0)

单行(正则表达式中的正则表达式):

s/^(.*'.*)$/my $x = $1; $x =~ s:\\?':\\':g; "'$x'"/me;

变为:

%3 successful login (test test's test\'s test\\'s test\\\'s string) alert for user %1 from %2|%3 successful login alert|root
%3 successful login (test test's test\'s test\\'s string) alert for user %1 from %2|%3 successful login alert|root
%3 successful login (test test's test\'s string) alert for user %1 from %2|%3 successful login alert|root
This is a normal string.
Line ending in;

成:

'%3 successful login (test test\'s test\'s test\\'s test\\\'s string) alert for user %1 from %2|%3 successful login alert|root'
'%3 successful login (test test\'s test\'s test\\'s string) alert for user %1 from %2|%3 successful login alert|root'
'%3 successful login (test test\'s test\'s string) alert for user %1 from %2|%3 successful login alert|root'
This is a normal string.
Line ending in;

并且应该适用于旧版本的Perl。

如果您想将反斜杠的数量减少到始终为1反斜杠,请将内部正则表达式中的?更改为*