Apologies on the inadvertent "broken links". The angle brackets have a different meaning here than in my example. A side question, is there a way to suppress that behavior?
Replacing numerics in text using regular expressions.
6 次查看(过去 30 天)
显示 更早的评论
Hello, I am trying to figure out whether it is possible to dynamically replace numeric values in a long text block using regular expressions. Here is an example from a made-up xml file.
str = '<document><placemark><when>5</when><lat>41</lat></placemark><placemark><when>11</when></placemark></document>';
Now, I want to perform some numerical function on all of the outputs of <when>, lets say subtract 3 so that the string will read
'<document><placemark><when>2</when><lat>41</lat></placemark><placemark><when>8</when></placemark></document>';
I can already find the locations using
exp='<when>(\d+)</when>'
but I don't know how to
- extract the actual numerical value at that location,
- perform some arbitrary function on that value (subtraction, addition, division, anything)
- write that new value back into the string so it reads <when>newValue</when>
If I was certain that the number of characters would stay the same, I could do a for-loop with some pretty gross indexing. However, as in the above example the length of the charstring representing the numeric value might change as a result of my function (11 became 8).
I suspect there is either a really elegant regexp solution, or it is not possible at all. Hoping for the former. Cheers, Dan
3 个评论
Walter Roberson
2017-9-28
Sometimes for presentation purposes here you need to change < to < which shows up like <
采纳的回答
Cedric
2017-9-28
编辑:Cedric
2017-9-28
pattern = '(?<=<when>)\d+' ;
values = str2double( regexp( str, pattern, 'match' )) ;
values = values - 3 ; % Some operation.
fSpec = regexprep( str, pattern, '%d' ) ; % Make input str a formatSpec ;)
newStr = sprintf( fSpec, values ) ;
Got to run, I will answer more tonight if you don't get a better answer.
Ok, got 5 more minutes, otherwise a good alternative was mentioned by Walter and is based on the fact that you can run MATLAB code within the replacement pattern:
repFun = @(s) sprintf( '%d', sscanf( s,'%d' ) - 3 ) ; % Update function.
newStr = regexprep( str, '(?<=<when>)\d+', '${repFun($0)}' ) ;
Finally a more "classical" approach, that matches and splits the input string, replaces the matches and rebuilds the output.
[numbers, parts] = regexp( str, '(?<=<when>)\d+', 'match', 'split' ) ;
numbers = arrayfun( @(x) sprintf( '%d', x ), str2double( numbers ) - 3, ...
'UniformOutput', false ) ;
buffer = [parts; [numbers, {''}]] ;
newStr = sprintf( '%s', buffer{:} ) ;
2 个评论
Cedric
2017-9-28
I updated the answer after you accepted it (@ 20:58 UTC), adding a more classical approach.
更多回答(1 个)
Walter Roberson
2017-9-28
Yes. If you can devise a regexp pattern to isolate the number, then you can use regexprep with the ${cmd} replacement. Arguments to the commands will be passed as strings. Values can be returned as strings or as integers that will be converted to strings.
For example,
str = '<document><placemark><when>5</when><lat>41</lat></placemark><placemark><when>11</when></placemark></document>';
regexprep(str, '\d+', '${$0 - 2}')
I did not test this code (my system is busy at the moment)
2 个评论
Cedric
2017-9-28
You could have done it by coding the conversion to double as well. $0 refers to the match, which is a string. It must be converted to double before you can do math. Instead of loading the replacement string with commands, I created a function repFun that we call, and this function does the double conversion string-num-string.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Characters and Strings 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!