Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Matlab中使用regexprep用不同的值替换文本中的许多匹配项_Regex_Matlab - Fatal编程技术网

如何在Matlab中使用regexprep用不同的值替换文本中的许多匹配项

如何在Matlab中使用regexprep用不同的值替换文本中的许多匹配项,regex,matlab,Regex,Matlab,我正在使用Matlab中的函数将模式的几个实例替换为单元格数组中的值列表。其思想是用第一个值替换第一个匹配,用下一个值替换第二个匹配,依此类推。因此,每个匹配项都替换为单元格数组中的不同值 我从报纸上读到: 如果replace是由N个字符向量组成的单元格数组,而expression是单个字符向量,则regexprep尝试N个匹配和替换 下面是我的一个任务示例(在这个示例中,假设我知道只有4个匹配项): 结果是: new_str = '111 s;dlf kudnbv. soergi; 1

我正在使用Matlab中的函数将模式的几个实例替换为单元格数组中的值列表。其思想是用第一个值替换第一个匹配,用下一个值替换第二个匹配,依此类推。因此,每个匹配项都替换为单元格数组中的不同值

我从报纸上读到:

如果
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'