[英]How can I replace the Nth instance of a string in PHP?
I need to dynamically add an active class to a shortcode in wordpress based on the active number set in it's parent shortcode. 我需要根据其父简码中设置的有效数字为wordpress中的简码动态添加一个有效类。
The parent looks like this: 父母看起来像这样:
$active = 3;
$output .= "\n\t\t".wpb_js_remove_wpautop($content);
The $content variable can technically consist of anything in between the shortcodes tags, but specifically, should include more child shortcodes (it's a tabs shortcode so the parent is tabs and the children are tab). 从技术上说,$ content变量可以由shortcodes标记之间的任何内容组成,但是具体来说,应该包含更多的子级短代码(这是一个tabs短代码,因此父级是tabs,子级是tab)。
What I need to do is parse $content
and replace the Nth ( $active
variable) instance of [vc_tab
with [vc_tab active="true"
我需要做的是解析
$content
并将[vc_tab
的第N个( $active
变量)实例[vc_tab
为[vc_tab active="true"
I realize there are better ways to design the shortcode to compensate for this but I am limited in what I can do because I am modifying Visual Composer to use Bootstrap tabs instead of jQuery and Bootstrap tabs need the active class on both the <li>
and the <div class="tab-pane">
elements but I don't want the users to have to add an active number to the parent shortcode and an active true/false to the child as that will get confusing. 我意识到有更好的方法来设计短代码来弥补这一点,但是我只能做些限制,因为我正在修改Visual Composer以使用Bootstrap选项卡而不是jQuery,并且Bootstrap选项卡在
<li>
和<div class="tab-pane">
元素,但我不希望用户必须在父简码中添加一个有效数字,在子代中添加一个有效的true / false,因为这会造成混淆。
So far from googling I can only find replacing the first occurrence or all occurrences, not the Nth one. 到目前为止,我只能查找代替第一个或所有出现的位置,而不是第N个出现的位置。
Temporarily I am using jQuery to make the appropriate <div>
active but it results in an undesirable FOUC where there is no pane visible on load and then one pops into place when the jQuery runs. 暂时,我正在使用jQuery激活适当的
<div>
但它导致了不良的FOUC,即在加载时没有可见的窗格,然后在运行jQuery时弹出一个窗格。
$('.tabs-wrap').each(function(){
var activeTab = $(this).find('.tabbed li.active a').attr('href');
$(this).find(activeTab).addClass('active');
});
I 'm not familiar with the tools you mention so I can't say if there is a better way to achieve the end goal, but you can replace the Nth occurrence of something using preg_replace_callback
: 我不熟悉您提到的工具,因此无法确定是否有更好的方法来实现最终目标,但是您可以使用
preg_replace_callback
代替第N次出现的事情:
$active = 3; // target occurrence
$occurrence = 0; // counter
$output = preg_replace_callback(
'/\[vc_tab/',
function ($matches) use(&$occurrence, $active) {
return ++$occurrence != $active
? $matches[0]
: '[vc_tab active="true"';
},
$output,
$active
);
This works by replacing each occurrence with itself unless the occurrence counter is equal to the target number. 除非事件计数器等于目标编号,否则通过用自身替换每个事件来进行工作。
Note that I have passed $active
as the maximum number of occurrences to replace in order to get free performance increase; 请注意,我已经通过
$active
作为替换的最大次数来获得免费的性能提升。 this will cause preg_replace_callback
to stop after $active
occurrences have been replaced (we know that all occurrences after that will be replaced by themselves, so there's no point in going on). 这将导致
preg_replace_callback
在替换$active
事件后停止(我们知道之后的所有事件都将被它们自己替换,因此没有意义了)。
This is an interesting problem, and got me thinking if you really need a regex to do this. 这是一个有趣的问题,让我想如果你真的需要一个正则表达式来做到这一点。
My conclusion is that I don't believe you do. 我的结论是,我不相信你。 All you need to do is find the occurrence of the
Nth
$needle
, and replace it with your replacement. 您需要做的就是找到
Nth
$needle
,并将其替换为替换项。 This can be achieved through some simple string manipulation, as follows: 这可以通过一些简单的字符串操作来实现,如下所示:
Define some variables. 定义一些变量。 Your input string, your
$active
index, the $needle
that we are looking for, and the $replace
ment that we will replace the Nth
match with. 您的输入字符串,您的
$active
索引,我们要寻找的$needle
以及将替换第Nth
匹配项的$replace
replacement。
$string = "[vc_tab [vc_tab [vc_tab [vc_tab [vc_tab [vc_tab"; $active = 3; $needle = "[vc_tab"; $replace = '[vc_tab active="true"';
Now, we need to make sure that there are enough $needle
s in the $string
, otherwise we can't do this replacement. 现在,我们需要确保
$string
中有足够的$needle
,否则我们将无法进行替换。
if( substr_count( $string, $needle) < $active) { throw new Exception("There aren't enough needles in the string to do this replacement"); }
Now, we know we can do the replacement. 现在,我们知道可以进行替换了。 So let's find the
$index
in the string where the Nth
occurrence of $needle
ends: 因此,让我们在
Nth
次出现的$needle
结尾的字符串中找到$index
:
$count = 0; $index = 0; while( $count++ < $active) { $index = strpos( $string, $needle, $index) + strlen( $needle); }
Now, $index
is pointing here in the string: 现在,
$index
在字符串中指向此处:
[vc_tab [vc_tab [vc_tab [vc_tab [vc_tab [vc_tab ^ Here
We can now do some simple substr()
's to form the final string: 现在,我们可以执行一些简单的
substr()
来形成最终的字符串:
$result = substr( $string, 0, $index - strlen( $needle)) . $replace . substr( $string, $index); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^ Before the Nth match After the Nth match
So, we end up concatenating: 因此,我们最终进行了串联:
[vc_tab [vc_tab
[vc_tab active="true"
[vc_tab [vc_tab [vc_tab
This results in our final output : 结果是我们的最终输出 :
[vc_tab [vc_tab [vc_tab active="true" [vc_tab [vc_tab [vc_tab
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.