【问题标题】:Replace $x<y$ by $x < y$将 $x<y$ 替换为 $x < y$
【发布时间】:2016-07-28 14:14:21
【问题描述】:

我想在文本中搜索美元符号之间的小于号 &lt;,例如 $x&lt;y$,并将其替换为 $x &lt; y$

我正在使用 mathjax,小于号导致渲染 Mathjax 时出现一些问题。(参见此处:http://docs.mathjax.org/en/latest/tex.html#tex-and-latex-in-html-documents)。

我试过了 $text = preg_replace("/\$(.*?)(&lt;)(.*?)\$/","/\$$1 &lt; $3\$/",$text) 但我不确定这是否是一个好的解决方案。我是编程新手:)

感谢您的帮助。

【问题讨论】:

  • 您使用反斜杠而不是正斜杠的任何原因?我认为这可能是一个错误:)
  • 您是否只想在$&lt; 符号之间允许一个字符;还是您要检查 PHP 变量?也许regex101.com/r/hO7cX5/1
  • @NathanRobb 你是对的,已编辑。
  • 这个问题让我想起了这个答案:stackoverflow.com/questions/1732348/…
  • 您如何准确定义“美元符号之间”?因为我们没有不同的开始和结束符号(与括号不同),所以文档中第一个和最后一个美元符号之间的所有内容都将介于两者之间。例如。句子1$sentence2$sentence3$sentence4$sentence5$sentence6$sentence7。 Sentence2-6 在两个美元符号之间,但我认为,这不完全是你想要的。

标签: php regex


【解决方案1】:

我编辑了我之前的答案 - 现在试试这个:

$text = preg_replace('/\$([^$&lt; ]+)&lt;([^$&lt; ]+)\$/','$$1 &lt; $2$', $text);

DEMO

【讨论】:

  • 谢谢,但这也替换了所有不在美元符号之间的&lt;
  • 嗯,它们可能在美元符号之间,但它的向后或向前看比预期的要远得多。
  • @BrandonHorsley 我正在使用降价编辑器。因此,例如这将用&lt; br&gt; 替换&lt;br&gt;,这是不好的。所以我只想替换那些在美元符号之间的&lt;
  • 不适用于$x&lt;y&lt;z$(请参阅此评论:stackoverflow.com/questions/38639028/replace-xy-by-x-y/…
【解决方案2】:

我认为这太复杂了,无法用正则表达式认真完成......

只要在$ 符号之间有固定数量的&lt;,就很容易(参见the answer from n-dru)。

但你在这里:

$output = preg_replace(<<<'REGEX'
(\$\K\s*((?:[^<$\s]+|(?!\s+[<$])\s+)*)\s*(?=(?:<(*ACCEPT)|\$|$)(*SKIP)(*F))
# \$\K => avoid the leading $ in the match
# ((?:[^<$\s]+|(?!\s+[<$])\s+)*) => up to $ or <, excluding surrounding spaces
# (?=(?:<(*ACCEPT)|\$|$)(*SKIP)(*F)) => accept matches with <, reject these without
|(?!^)<\K\s*((?:[^<$\s]+|(?!\s+[<$])\s+)*)\s*(\$|)
# (?!^) => to ensure we are inside $ ... $
# <\K => avoid the leading < in the match
|[^$]+(*SKIP)(*F)
# skip everything outside $ ... $
)x
REGEX
, " $1$2 $3", $your_input);

另见:https://regex101.com/r/fP9aG5/2

我知道,您要求$x&lt;y&lt;z$ => $x &lt; y &lt; z$(而不是$ x &lt; y &lt; z $),但这对于正常的替换模式是不可行的。为此需要preg_replace_callback

$output = preg_replace_callback(<<<'REGEX'
(\$\K\s*((?:[^<$\s]+|(?!\s+[<$])\s+)*)\s*(?=(?:<(*ACCEPT)|\$|$)(*SKIP)(*F))
|(?!^)<\K\s*((?:[^<$\s]+|(?!\s+[<$])\s+)*)\s*(\$|)
|[^$]+(*SKIP)(*F))x
REGEX
, function($m) {
    if ($m[1] != "") return "$m[1] ";
    if ($m[3] != "") return " $m[2]$m[3]";
    return " $m[2] ";
}, $your_input);

我已尝试使用 $your_input:

random < test
nope $ foo $ bar < a $ qux < biz $fx<hk$
$foo<bar<baz$ foo  buh < bar < baz $
$ foo $ a < z $ a < b < z $

有了这个 preg_replace_callback,我得到了,正如预期的那样:

random < test
nope $ foo $ bar < a $qux < biz$fx<hk$
$foo<bar<baz$foo  buh < bar < baz$
$ foo $ a < z $a < b < z$

【讨论】:

  • 感谢您的回答。它工作得很好。一些数学公式介于 $$Formula$$ 之类的双美元之间。是否有可能让代码以双倍的价格工作?
  • @mac 仅当您在双美元之间不使用单美元并且您的代码格式正确时。在这种情况下,您可以将所有出现的\$ 复制到\$\$ ......问题是正则表达式没有无限的后视。请下次您提出正则表达式问题时,指定所有可能的输入/预期输出(或匹配)。然后我们可以为您提供量身定制的正则表达式解决方案。
【解决方案3】:

我尝试组装这个正则表达式。 试试看,如果它符合您的要求。

$text = preg_replace("/\\$(.{1,20})<(.{1,20})\\$/", "\$$1 < $2\$", $text);

在此表达式中,您有 {1,20},您可以将其用作参数,即左侧和右侧的最大长度(在本例中为 20)可以是您的变量。

【讨论】:

  • 谢谢。所以这仅适用于 &lt; 之前有 20 个字符和之后有 20 个字符的方程?
  • 是的,完全正确。如果你想改变它,例如到 50,将数字从 {1,20} 更改为 {1,50}。通常这是{min, max} 字符长度限制。您在表达式中有两次此定义。左边是&lt; 之前的字符。右边是&lt;之后的字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
  • 1970-01-01
相关资源
最近更新 更多