preg_replace只替换两个符号之间的字符串,如果它包含特定的

时间:2016-03-01 16:18:38

标签: php regex

我试图只替换两个符号之间的字符串,并在字符串包含特定字时开始替换,例如:

$string = '%Test% %font-style:italic; font-weight:bold;%'; //It Can be with different orders such as
$string = '%Test% %font-weight:bold; font-style:italic;%'; 

所以我想要使用preg_replace for的字符串是这两个符号%%之间的字符串,我想使用preg_replace,如果字符串包含一个css标签,例如font-style:italic; color:red; font-weight:bold; etc.. I&#39我试过了

$string = preg_replace('`\%(.*?)((.*?):(.*?);)(.*?)\%`si', '(span style="$2$5")', $string); // ( used as start tag html symbol

但是当我用它

时它引起了一个问题
http://localhost/NaiTreNo/Games/Games/BatMan%20Arkham%20Knight/Image/Cover.jpg :D %color:blue; font-weight:bold;%

它应该返回:

http://localhost/NaiTreNo/Games/Games/BatMan%20Arkham%20Knight/Image/Cover.jpg :D
<span style="color:blue; font-weight:bold;">

但它回来了:

http://localhost/NaiTreNo/Games/Games/BatMan<span style="20Arkham%20Knight/Image/Cover.jpg :D %color:blue; font-weight:bold;%">

请帮忙。

2 个答案:

答案 0 :(得分:3)

regex太宽松了。它只检查字符串中某处:;的存在。我会使用CSS属性名称具有特定格式的知识来制定regex规则,该规则不会匹配包含:;的任何字符串。

例如,像这样:

#%(([a-z]+(-[a-z]+){0,2}: *[^;]+;)+)(.*?)%#si

CSS property name以包含一个或多个小写字母[a-z]+的单词开头,后跟零,一个或两个以上的单词,每个单词前面都有一个短划线(-[a-z]+){0,2}

也可以创建限制用于值的过于接受的.*?的规则,但结果不会付出努力(并且regex变得难以理解。

regex如何运作:

%                      # your custom boundary start symbol
  (                    # start of group #1 used to capture the CSS rules
    (                  # start of group #2 that captures a single CSS rul
      [a-z]+           # first word of CSS property name
      (-[a-z]+){0,2}   # 0-2 more words, separated with dash (-)
      : *              # the colon followed by optional white spaces
      [^;]+;           # anything until the first semicolon (at least one character)
    )+                 # end of group #2; it can repeat; at least one occurence is required
  )                    # end of group #1
  (.*?)                # captures everything after the last semicolon
%                      # your custom boundary end symbol

当只有一个CSS属性并且其值后面没有分号(f.e)时,上面的regex不匹配。 %color: red%。为了解决这个问题,第2组之后的+符号必须替换为*(以匹配零个或多个以;结尾的CSS规则)但这样结束{{1将匹配任何内容,包括(.*?)或示例中的网址。

可以通过将最后一组中的Test替换为组#2的内容而不使用结尾.*?来解决此问题。表达变得更长,更难以理解,我不会在这里发布。最好确保CSS规则始终以分号(;)结尾,包括最后一个分号。

可以在https://regex101.com/r/vC1oS2/3

找到此;的游乐场

答案 1 :(得分:0)

我可以建议在开头添加一个空格。

-

尝试https://3v4l.org/uubF7