如何在Matlab中使用regexprep用不同的值替换文本中的许多匹配项
我正在使用Matlab中的函数将模式的几个实例替换为单元格数组中的值列表。其思想是用第一个值替换第一个匹配,用下一个值替换第二个匹配,依此类推。因此,每个匹配项都替换为单元格数组中的不同值 我从报纸上读到: 如果如何在Matlab中使用regexprep用不同的值替换文本中的许多匹配项,regex,matlab,Regex,Matlab,我正在使用Matlab中的函数将模式的几个实例替换为单元格数组中的值列表。其思想是用第一个值替换第一个匹配,用下一个值替换第二个匹配,依此类推。因此,每个匹配项都替换为单元格数组中的不同值 我从报纸上读到: 如果replace是由N个字符向量组成的单元格数组,而expression是单个字符向量,则regexprep尝试N个匹配和替换 下面是我的一个任务示例(在这个示例中,假设我知道只有4个匹配项): 结果是: new_str = '111 s;dlf kudnbv. soergi; 1
replace
是由N个字符向量组成的单元格数组,而expression
是单个字符向量,则regexprep尝试N个匹配和替换
下面是我的一个任务示例(在这个示例中,假设我知道只有4个匹配项):
结果是:
new_str =
'111 s;dlf kudnbv. soergi; 111va/.lge roins.br oian111a/ sergosr toibns111'
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444'
当然,这个结果是不正确的,因为所有匹配项都被单元格数组中的第一个值替换
所以我在谷歌上搜索了这个问题,找到了这个。显然,函数regexprep
逐个执行替换,因此在第一次替换之后,找到的第一个匹配是最初的第二个匹配,并且因为它被识别为第一个匹配,所以被单元数组中的第一个值替换(111)
我可以通过一个循环来解决这个问题,该循环每次都以不同的值执行此任务:
new_str = str;
for k = 1:numel(values)
new_str = regexprep(new_str,pattern,values(k),'once'); % raplace one value each time
end
结果是:
new_str =
'111 s;dlf kudnbv. soergi; 111va/.lge roins.br oian111a/ sergosr toibns111'
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444'
这正是我想要的
我的问题是如何编写模式
或使用regexprep
,以便在没有循环的情况下获得相同的结果?在我看来,我在如何使用这个函数方面遗漏了一些东西。我还要补充一点,我真正的问题是文本中有100多个匹配项,因此使用像
([a][b][c])(.*)([a][b][c])(.*)(.*)([a][b][c])(.*)([a][b][c])
这样的模式和像111$2222$4333$6444
这样的替换模式(在这里给出正确的结果)实际上不是一个选项
任何帮助都将不胜感激 您可以制作一个基本的助手字符串生成器,并使用命令执行替换令牌 例如:
classdef strgenerator < handle
properties
strs
ii = 1
end
methods
function self = strgenerator(strs)
self.strs = strs;
end
function outstr = nextstr(self)
outstr = self.strs{self.ii};
self.ii = self.ii + 1;
if self.ii > numel(self.strs)
self.ii = 1;
end
end
end
end
为我们提供:
>> SOcode
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444'
使用@excaza idea,我编写了一个更简单的实现,面向那些在Matlab中没有真正使用OOP的人(比如我): 我们从一个helper函数开始,该函数从上一个函数调用中记住索引,并从其输入返回下一个单元格
strCellArray
:
function out = nextStr(strCellArray)
persistent n
if isempty(n) || n>numel(strCellArray)
n = 1;
end
out = strCellArray{n};
n = n+1;
end
然后我们可以写:
values = {'111','222','333','444'}; % the cell array
new_str = regexprep(str,pattern,'${nextStr(values)}'); % execute the command between {...} on every call to the function
clear nextStr % to reset the counter in the function
得到同样的结果:
111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444
这里需要注意的是,尽管我们只调用
regexprep
一次,但实际上它被连续调用了N次,因此最后一个参数中的命令被计算了N次。根据问题中链接的文档,regexprep(str,pattern,values)
,使用值
字符串单元格数组和模式
单个字符串,对值
中的每个元素应用一次搜索和替换。因此,它相当于:
str = regexprep(str,pattern,values{1});
str = regexprep(str,pattern,values{2});
str = regexprep(str,pattern,values{3});
... etc.
在第一次替换之后,模式
不再出现在str
中,因此第二次(以及后续)替换找不到任何匹配项。也就是说,每次调用regexprep
都将替换所有匹配项。相反,regexprep(…,'once')
将只替换第一个匹配项
因此:
将完全按照需要执行:
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444 abc/abc'
注意我在字符串的末尾又添加了两个“abc”元素,注意这些元素没有被替换<代码>值有4个元素,然后只替换前4个匹配项。谢谢您的回答。这很有趣,您基本上在新对象中创建了一种“while”循环,因此它在外部代码中是看不见的。我必须承认,我希望有一个更简单的解决方案,尽管最终结果(调用
regxprep
)非常优雅,但它不必是类,它只是保持生成器状态的最简单方法。替换可以是任何函数,只要它输出文本。我以前用过一个匿名函数。有趣的是,我刚刚在这里用一个函数为它写了另一个实现……顺便说一句,在循环中,你最好使用regexprep而不是regexprep
,可能更快。@UnrableLightness如果模式像本例中那样简单,那么你可能是对的。但我真正的问题更复杂,所以我也需要正则表达式来找到正确的匹配项。下面是我的建议,我明白。好办法!克里斯的答案正是你想要的。我被这两个问题弄糊涂了。顺便说一下,我想我找到了另一个问题的解决办法。用str='abc(1,2,3,1,2,3)';模式={'1','2','3'};值={'7','8','9'};new_str=regexprep(str,pattern,values)
new_str是abc(7,8,9,7,8,9)
。采取str='abc(1,2,3)';模式={'\d','\d','\d'};值={'7','8','9'};new_str=regexprep(str,pattern,values)
,输出字符串为abc(9,9,9)
,并带有'one'选项abc(9,2,3)
。这是我在之前的评论中提到的行为,但是我想我误解了你的意思。好的解决方案+1虽然循环可能会更快。我想你是对的,但如果速度不是问题,那么这具有可重用的优势好的解决方案,+1,我想我混淆了这两个问题。太好了!这就是我在调用函数时错过的。谢谢在这里,我认为我很聪明,而答案并不需要这么聪明
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444 abc/abc'