我正在Matlab中使用函数regexprep
用单元格数组中的值列表替换模式的几个实例。这个想法是用第一个值替换第一个匹配项,用下一个替换第二个匹配项,依此类推。因此,每个匹配项都替换为单元格数组中的 different 值。
从documentation中我读到:
如果
replace
是N个字符向量的单元格数组,而expression
是单个字符向量,则regexprep会尝试N个匹配项和替换项。
这是我所执行任务的一个示例(对于此示例,假设我知道只有4个匹配项):
% some text:
str = 'abc s;dlf kudnbv. soergi; abcva/.lge roins.br oianabca/ sergosr toibnsabc';
pattern = '([a][b][c])'; % the patern to match
values = {'111','222','333','444'}; % the cell array
new_str = regexprep(str,pattern,values) % the actual raplace
结果:
new_str =
'111 s;dlf kudnbv. soergi; 111va/.lge roins.br oian111a/ sergosr toibns111'
当然,此结果是不正确的,因为所有匹配项都被替换为单元格数组中的第一个值。
因此,我搜索了这个问题并找到了explanation。显然,函数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; 222va/.lge roins.br oian333a/ sergosr toibns444'
这正是我想要的。
我的问题是如何编写pattern
或使用regexprep
才能获得无循环的相同结果?
在我看来,我对如何使用此功能有些怀念。我还要补充一点,我的真正问题是文本中有100多个匹配项,因此,实际上不能使用([a][b][c])(.*)([a][b][c])(.*)([a][b][c])(.*)([a][b][c])
这样的模式和111$2222$4333$6444
这样的替换模式(在此处给出正确的结果)
任何帮助将不胜感激!
答案 0 :(得分:4)
您可以制作一个基本的辅助字符串生成器,并使用命令执行替换令牌。
例如:
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
和
str = 'abc s;dlf kudnbv. soergi; abcva/.lge roins.br oianabca/ sergosr toibnsabc';
pattern = '([a][b][c])'; % the patern to match
values = strgenerator({'111','222','333','444'}); % the cell array
new_str = regexprep(str,pattern,'${values.nextstr()}') % the actual raplace
为我们提供:
>> SOcode
new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444'
答案 1 :(得分:3)
根据问题中链接的文档regexprep(str,pattern,values)
,其中values
是字符串的单元格数组,而pattern
是单个字符串,则应用搜索并为{中的每个元素替换一次{1}}。因此,它等效于:
values
在第一次替换之后,str = regexprep(str,pattern,values{1});
str = regexprep(str,pattern,values{2});
str = regexprep(str,pattern,values{3});
... etc.
中不再存在pattern
,因此第二次(及后续)替换找不到任何匹配项。也就是说,每次调用str
都会替换所有匹配项。相反,regexprep
仅替换第一个匹配项。
因此:
regexprep(...,'once')
将完全按照期望进行操作:
str = 'abc s;dlf kudnbv. soergi; abcva/.lge roins.br oianabca/ sergosr toibnsabc abc/abc';
pattern = '([a][b][c])'; % the patern to match
values = {'111','222','333','444'};
new_str = regexprep(str,pattern,values,'once')
请注意,我在字符串的末尾添加了两个“ abc”元素,并注意这些元素并未被替换。 new_str =
'111 s;dlf kudnbv. soergi; 222va/.lge roins.br oian333a/ sergosr toibns444 abc/abc'
有4个元素,则仅替换前4个匹配项。
答案 2 :(得分:2)
我使用@excaza的想法,为在Matlab中不真正使用OOP的人们(像我一样)编写了一个更简单的实现:
我们从一个辅助函数开始,该函数会记住上次调用该函数的索引,并从其输入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次。