MATLAB中用一个有效的方法替换/插入一个符号(符号系列)与其他几个符号相对应的替换符号是什么?
例如,考虑使用字符串Eq
:Eq = 'A*exp(-((x-xc)/w)^2)'
。有没有办法将*
替换为.*
,/
替换为./
,\
替换为.\
,^
替换为.^
{1}}没有写出四条单独的strrep()
行?
答案 0 :(得分:3)
Regular expressions可以很好地完成这项工作。正则表达式只是在文本中找到模式。您可以通过正则表达式指定要查找的模式类型,输出将为您提供模式发生位置的位置。
对于我们的特定情况,我们不仅希望找到模式发生的位置,还希望用其他东西替换这些模式。具体来说,使用MATLAB中的函数regexprep
将字符串中的匹配替换为其他内容。您要做的是在每个符号前面添加*
替换所有/
,\
,^
和.
符号。
regexprep
的工作原理是第一个输入是您正在查看的字符串,第二个输入是您尝试查找的模式。在我们的示例中,我们希望找到{strong>任何 *
,/
,\
和^
。要指定此模式,请将这些所需符号放在[]
括号中。正则表达式保留\
作为特殊符号来描述可以被解析为正则表达式但实际上不是正常表达的字符。因此,您需要\\
字符使用\
,\^
字符使用^
。第三个输入是您想要替换每个匹配的内容。在我们的例子中,我们只想重用每个匹配的字符,但我们在匹配开始时添加.
。这是通过在正则表达式语法中执行\.$0
来完成的。 $0
表示获取匹配产生的第一个令牌......这实际上是模式中匹配的符号。 .
也是使用正则表达式的保留关键字,因此我们必须在此符号前加上\
字符。
没有进一步的麻烦:
>> Eq = 'A*exp(-((x-xc)/w)^2)';
>> out = regexprep(Eq, '[*/\\\^]', '\.$0')
out =
A.*exp(-((x-xc)./w).^2)
我们正在寻找的模式是[*/\\\^]
,这意味着我们希望找到*
,/
,\
中的任何一种 - 表示为\\
在正则表达式中,\^
- 在正则表达式中表示为^
。我们希望找到这些符号中的任何一个,并在前面添加.
字符替换为相同的符号 - \.$0
。
作为一个更复杂的例子,让我们确保在示例公式中包含您正在寻找的所有符号:
>> A = 'A*exp(-((x-xc)/w)^2) \ b^2';
>> out = regexprep(A, '[*/\\\^]', '\.$0')
out =
A.*exp(-((x-xc)./w).^2) .\ b.^2
答案 1 :(得分:3)
我会像rayryeng's answer一样使用regexp
。但这是另一种方法,只是为了提供替代方案。
ops = '*/\^'; %// operators that need a dot
ii = find(ismember(Eq, ops)); %// find where dots should be inserted
[~, jj] = sort([1:numel(Eq) ii-.5]); %// will be used to properly order the result
result = [Eq repmat('.',1,numel(ii))]; %// insert dots at the end
result = result(jj); %// properly order the result
一个变种:
ops = '*/\^'; %// operators that need a dot
ii = find(ismember(Eq, ops)); %// find where dots should be inserted
jj = sort([1:numel(Eq) ii-.5]); %// dot locations are marked with fractional part
result = Eq(ceil(jj)); %// repeat characters where the dots will be placed
result(mod(jj,1)>0) = '.'; %// place dots at indices with fractional part
答案 2 :(得分:1)
vectorize
函数几乎已经完成了您想要的所有功能,但它不会将mldivide
(\
)转换为ldivide
(.\
)。
通过“高效”,您的意思是更少的代码行还是更快?正则表达式几乎总是比其他方法慢,而且可读性较差。在这种情况下,我不认为它们是必要的或者是一个好的选择。如果你只需要将你的字符串转换一次,那么速度就不是可读性了(strrep
仍然会更快)。如果您需要多次执行此操作,您提到的这个简单代码对于像您的示例那样的短字符串比regexrep
快4-5倍(并且对于更长的字符串来说要快得多):
out = strrep(Eq,'*','.*');
out = strrep(out,'/','./');
out = strrep(out,'\','.\');
out = strrep(out,'^','.^');
如果您想要一行,请使用:
out = strrep(strrep(strrep(strrep(Eq,'*','.*'),'/','./'),'\','.\'),'^','.^');
也会稍快一些。或者创建自己的vectorize
版本并调用它。
正则表达式闪耀在更复杂的情况下,例如,如果您的字符串已经部分矢量化:Eq = 'A.*exp(-((x-xc)/w)^2)'
。即便如此,vectorize
函数只使用strrep
,然后调用strfind
“删除任何可能的'..*'
,'../'
等。”并使用适当的元素操作符替换它们,因为它更快(例如,符号数学字符串可能变得非常大)。