我想找到标签和返回之间没有行缩进的行。 例如:
myLabel:
bla
if(no)
return
else
foo
return
如果我最后一次使用其他词语。例如发送它有效。
$r1 = '^(\w[\w\d_]*:\s*\n((?!\nreturn).)*)(\n[^\s][^n]*\n)((((?!\nreturn).)*)\nsend)'; ; working regex
但$ r2不起作用。 Perl崩溃。
$r2 = '^(\w[\w\d_]*:\s*\n((?!\nreturn).)*)(\n[^\s][^n]*\n)((((?!\nreturn).)*)\nreturn)'; ; dont working regex
以下是php中用于测试的示例
$str = '^(\w[\w\d_]*:\s*\n((?!\nreturn).)*)(\n[^\s][^n]*\n)((((?!\nreturn).)*)\nreturn)';
$actual = preg_replace('/^'.$str.'/smi', "$1" . $indentStr . "$2$3", $actual);
如果这不起作用,那么我将使用循环抛出所有源代码行。 我将使用它来使用此工具来完善Autohotkey源代码:https://github.com/sl5net/SL5_AHK_Refactor_engine
答案 0 :(得分:2)
你的模式非常复杂,使用着名的#34;技巧:((?!\nreturn).)*
这个很慢,如果子模式失败后也不会阻止很多回溯。
您可以用更简单的方式编写模式:
$pattern = '~^\w+:\R(?:\N*\R)*?return$~m';
细节:
~ # pattern delimiter
^ # anchor for the start of the line (m option)
\w+: # the label name
\R # alias for any kind of newline sequences
(?:\N*\R)*? # lines until (non-greedy number of line)
return # "return"
$ # end of the line (remove it if uneeded)
~m # pattern delimiter, multiline option
\N
匹配除换行符之外的任何字符(无论是否为单行)。在这种情况下,您可以用点替换它,但它不太明确。
\R
是几个新行序列\r\n
,\n
或更具异国情调的别名。如果您已经知道字符串中使用了哪种换行符序列,请将其替换为此序列。
简而言之,该模式旨在测试一行是否以" return"但只在行的开头(不是在字符串的所有位置)。
答案 1 :(得分:0)
我找到了一个实现。它完美无缺。它缩进标签正文并且不会打扰周围的内容。以下是实施:https://github.com/sl5net/SL5_AHK_Refactor_engine/blob/master/phpdesktop-msie-1.14-php-5.4.33/www/SL5_preg_contentFinder/examples/AutoHotKey/Reformatting_Autohotkey_Source.php#L192
$pattern = '/^(\w+:)(\h*\n)(?:.*\n)*?(return)/m';
$label = '^\w[\w\d_]*:';
$pattern = '/' . "($label)(\h*\R)((?:.*\n)*?)(return\b)" . '/im';
preg_match_all($pattern, $actual, $matches,PREG_OFFSET_CAPTURE);
$labelsAr = $matches[1];
$contentAr = $matches[3];
$returnAr = $matches[4];
for($k = count($labelsAr) ; $k-- ; $k >=0 ) {
$new = $labelsAr[$k][0]
. "\n" . $indentStr
. rtrim( preg_replace('/\n/ism', "\n"
. $indentStr, $contentAr[$k][0]) )
. "\n" . ltrim($returnAr[$k][0]) ;
$actual = substr($actual,0,$labelsAr[$k][1])
. $new
. substr($actual,$returnAr[$k][1] + strlen($returnAr[$k][0]) ) ;
}