PHP:如何将这个句子转换为给定格式

4
"[5|五]个令人难忘的旅行建议|五个令人无悔的旅行建议|[5|五]个令人惊叹的旅行技巧|五个令人惊叹的旅行建议"

"[5|五]个令人难忘的旅行建议~五个令人无悔的旅行建议~[5|五]个令人惊叹的旅行技巧~五个令人惊叹的旅行建议"
我可以使用 str_replace("|", "~", $code),但问题在于如果 "|""[ ]" 之间,我不想将其转换为 "~"

你的句子是作为任何变量的输入吗? - jeni
6个回答

4
for($i=0,$s=strlen($str),$c=0;$i<$s;++$i){
    if($str[$i]=='[')++$c;
    elseif($str[$i]==']')--$c;
    elseif(!$c && $str[$i]=='|')$str[$i]='~';
}

1

这个正则表达式应该可以做到你想要的 /^(?<!\[.)\|(?!].)/

结合使用 preg_replace,然后 klabamo 就可以了 :)

现在好像工作得更好了!

$sentence = "[5|five] [Tips|Suggestions] for an Unforgettable Trip~Five suggestions for a un-regret able Trip~[5|five] [tips|suggestions] for an [amazing|incredible] Trip~Five [tips|suggestions] for an astonishing Trip";

$newSentence = preg_replace("/^(?<!\[.)\|(?!].)/", "~", $sentence);

echo $newSentence;

不,它不起作用。你的“before”字符串和原帖中的“after”字符串是一样的;你的代码没有改变任何东西。 - Alan Moore

1
$in = "[5|five] [Tips|Suggestions] for an Unforgettable Trip|Five suggestions for a un-regret able Trip|[5|five] [tips|suggestions] for an [amazing|incredible] Trip|Five [tips|suggestions] for an astonishing Trip";
$out = preg_replace('/(?<=^|\])([^\[]*?)\|([^\[]*?)(?=\[|$)/s', '\1~\2', $in);

正则表达式的工作原理如下,只要不嵌套括号( [foo [bar]] ),就会正确无误。

(?<= ^ | \]) - 从字符串开头或跟随 ] 开始
([^\[]*?) - 捕获任何不是[的字符
\| - 我们想要替换的字符
([^\[]*?) - 再次捕获除了[以外任意数量的字符
(?= \[|$) - 在字符串结尾或在[之前停止匹配


这肯定有点过头了吧? - James
@James 我有点累可能会漏掉什么,但是看起来你的解决方案对于这个例子不会表现得很好,因为它无法匹配在 ]| 之间的任意数量的字符。这个可以正常工作。 - Jeremy
@James:你的正则表达式在preg_replace中不起作用,Jeremy的可以。为了减少开销,在我的正则表达式中我正在使用否定。 - hakre
我已更新了正则表达式并提供了一个示例。在这个测试案例中,它对我有效。 - James

0

您可以先使用 str_replace 替换所有内容,然后再重新替换那些在 [] 中的内容(Demo):

$subject = '[5|five] [Tips|Suggestions] for an Unforgettable Trip|Five suggestions for a 
un-regret able Trip|[5|five] [tips|suggestions] for an [amazing|incredible] Trip|Five [tips|suggestions] for an astonishing Trip';
$result = str_replace('|', '~', $subject);
$pattern = '((\[[^\]]*)~([^\[]*\]))';
$result = preg_replace($pattern, '$1|$2', $result);

var_dump($subject, $result);

这个也很好用,谢谢啊!太棒了! - Vinit Desai

0
如果您知道方括号始终会正确平衡且不会嵌套,那么简单的前瞻就足够了:
$after = preg_replace('/\|(?![^][]*+\])/', '~', $before);

演示

从管道字符后立即开始,前瞻扫描下一个右方括号。如果它在没有先看到左方括号的情况下找到一个右方括号,则管道必须在一对括号内部。不需要使用后行查找来检查开口括号,这很好,因为PHP(像大多数正则表达式)不支持变宽的后行查找。

我使用了负向前瞻,但是正向前瞻也可以正常工作:

$after = preg_replace('/\|(?=[^][]*+(?:\[|$))/', '~', $before);

演示

请注意,如果右方括号是字符类中列出的第一个字符(或者在否定符号^之后作为第一个字符),则无需对其进行转义。因此,“不是方括号”的奇怪写法是[^][]。而*+占有量词

如果方括号可以嵌套,则应该放弃使用正则表达式,改用@RiaD的解决方案。虽然仍然可能使用正则表达式,但会更加复杂。


我刚刚下载并尝试了一下,它真的非常好用!非常感谢您的热心帮助。 - Vinit Desai

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接