你可以用一个替换来做到这一点:
$txt = preg_replace('~^(?:TABLE\R|\G(?!\A)(?:END$|.+\R|.+\z))~m', '%$0', $txt);
请注意,此模式假定始终有一个结束 END“标签”。如果不是这种情况,替换将一直持续到空行(+ 量词的原因)或字符串结尾。
您还可以选择检查 TABLE 标记是否以 END 标记结束:
$pattern = '~^(?:TABLE\R(?=(?:.+\R)*?END$)|\G(?!\A)(?:END$|.+\R|.+\z))~m';
第一个模式细节:
^ # matches the start of a line
(?: # open a non-capturing group
TABLE \R # TABLE and a newline (CR, LF or CRLF)
| # OR
\G (?!\A) # contigous to a precedent match but not
# at the start of the string
(?: #
END $ # END at the end of a line
| #
.+ \R # a line (not empty) and a newline
| #
.+ \z # the last line of the string
) # close the non-capturing group
) #
其他前瞻细节:
(?= # open the lookahead
(?:.+\R)*? # matches zero or more lines lazily
END$ # until the line END
)
另一种方式
$arr = preg_split('/\R/', $txt);
$state = false;
foreach ($arr as &$line) {
if ($state || $line === 'TABLE') {
$state = ($line !== 'END');
$line = '%' . $line;
}
}
$txt = implode("\n", $arr);
此代码的行为与第一个模式相同,请注意,您获取的是一个带有 UNIX 格式换行符的字符串。