regex - 如何在 MATLAB 中验证 formatSpec 字符串?

标签 regex string matlab validation printf

MATLAB 中的许多函数(以及其他具有 c 派生的 scanf/printf 的函数)用于写入或读取字符串(仅举几例: sscanfsprintftextscan) 依赖于用户提供有效的 formatSpec 字符串,该字符串告诉函数结构要构建的字符串或要解析的字符串。我正在寻找一种方法来验证这样的 formatSpec 字符串,然后再使用它调用 sprintf .

对于sprintfformatSpec的结构描述为in the documentation并且如下:

MATLAB's sprintf formatSpec

我想特别指出formatSpec的两个方面:

  • (✓) A formatting operator starts with a percent sign, %, and ends with a conversion character.
  • (x) formatSpec can also include additional text before a percent sign, %, or after a conversion character.

我考虑的解决方案涉及使用正则表达式来测试传入的字符串。到目前为止,我所拥有的是一个似乎能够匹配初始 %转换字符之间的所有内容的表达式,但不是“附加文本”可能会出现。

(%{1}(\d+\$)?[-+\s0#]*(\d+|\*)?(\.\d+)?[bt]?[diuoxXfeEgGcs]+)+

我还想添加捕获“除 %'\ 之外的任何可打印文本字符的功能,除非这些字符完全显示两次”。这需要在初始 % 之前和转换字符 之后捕获。

  • 任何可打印字符:[ -~]
  • 除了 %'\:(?![\\%'] )
  • 这些字符正好出现两次:( §§§§ |'{2}|\\{2}|%{2})(§ = 占位符)

我在使用“unless”时遇到问题,即获取否定前瞻以丢弃单次出现但允许两次出现指定字符。

我有两个问题:

  1. 是否有更好的方法来验证 formatSpec 字符串(即不使用正则表达式,或使用更好的方法)?
  2. 如何修复我的正则表达式以使其按描述工作?

消歧义:在 formatSpec 字符串的情况下,格式化运算符 的两边都有“自由文本”,文本应被视为 的一部分strong>下一个 格式化运算符除非没有剩余。下面是一个 formatSpec 字符串应该如何使用正则表达式拆分的示例(其中 | 是每个匹配项的第一个字符):

Color %s, number1 %d, number2 %05d, hex %#x, float %5.2f, unsigned value %u.
|       |           |             |        |            |                   |

最佳答案

我在这上面花了一些时间,我想我已经接近了,所以我会在答案中写下我目前的进展。我相当肯定它仍然可以改进。

首先是代码,使用the nice example string by Ro Yo Mi :

% valid input
sample_good = 'Color %s, we are looking for %%02droids %% number1 %d, number2 %05d, hex %#x, float %5.2f, unsigned value %u.';
% invalid input: "%02 droids" has a single percent sign which is not part of an operator
sample_bad = 'Color %s, we are looking for %02 droids %% number1 %d, number2 %05d, hex %#x, float %5.2f, unsigned value %u.';

group_from = '(';
group_to = ')';
printable = '([ -$&-\[\]-~]|%%|\\\\)*';
atomic_op = '(?<!%)%(\d+\$)?[ +#-]*(\d+|\*)?(\.\d*)?[bt]?[diuoxXfeEgGcs]';

% pattern for full validation
full_patt = ['^' group_from printable atomic_op group_to '*' printable '$'];
% pattern for splitting valid strings
part_patt = [printable atomic_op];

% examples
matches_full_bad = regexp(sample_bad,full_patt);            % no match
matches_full_good = regexp(sample_good,full_patt);          % match
matches_parts_good = regexp(sample_good,part_patt,'match'); % sliced matches

第一个示例字符串是有效的,第二个字符串由于 %02 droids 是字符串的一部分而被破坏。我定义了一些辅助模式;请注意,其中大多数已经包含了组。 printable 模式使用除 %\ 外的所有 ASCII,加上 %%\\。请注意,为了匹配双反斜杠,我们需要在搜索表达式中使用四个反斜杠(两个转义反斜杠)。

我所说的 atomic_op 是一种匹配以百分号开头并以转换字符结尾的格式运算符的模式。它使用负向后视来避免匹配以 %% 开头的虚假格式运算符。由于懒惰,我采取了一些捷径(例如 te 在我的版本中有效)。对于不太邪恶的输入,它应该非常有用。

最重要的部分是full_pattpart_patt。前者尝试匹配完整的格式规范,以确定它是否有效。不幸的是,在嵌套组的情况下,MATLAB 仅存储最外层 级别的标记;在我们的例子中,这没有用。这就是 part_patt 发挥作用的地方:它只匹配“printable_string format_operator”。与 full_patt 一起使用,它可用于将您的完整字符串分割成有意义的贡献。请注意,part_patt 通常也会在其本地有效位置匹配无效字符串,因此两者确实必须一起使用。

考虑上面的具体例子:

>> matches_full_bad

matches_full_bad =

     []

>> matches_full_good

matches_full_good =

     1

>> matches_parts_good{:}

ans =

Color %s


ans =

, we are looking for %%02droids %% number1 %d


ans =

, number2 %05d


ans =

, hex %#x


ans =

, float %5.2f


ans =

, unsigned value %u

让我们分析一下结果。 “坏”模式返回一个(虚假的)空向量,而“好”模式返回一个(真实的)1 作为完整模式。然后部分模式正确返回输入的每个相关子模式。但是请注意,结果中缺少句子末尾的最后一个句点,因为我们匹配了 printable atomic_op block 。因为我们知道我们正在处理一个有效的字符串,所以字符串的其余部分(在最终匹配之后)应该分配给一个新的匹配,或者分配给最后一个匹配,这取决于您的偏好。

为清楚起见,以下是我想象的工作方式:

for sample={sample_bad,sample_good},
    if regexp(sample{1},full_patt)
        disp('Match found!');
        matches = regexp(sample,part_patt,'match');
        matches = matches{1};   % strip outermost singleton cell dimension
        for k=1:length(matches)
            fprintf('Format substring #%d: %s\n',k, matches{k});
        end
        %TODO: treat final printable part of the string
    else
        disp('Uh-oh, no match!')
    end
end

关于regex - 如何在 MATLAB 中验证 formatSpec 字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38169682/

相关文章:

matlab - 消除图像中两种颜色边缘的颜色过渡效果

c# - 需要帮助将包含空格的 bbcode URL 转换为有效的 Markdown

javascript - 检查 '\' 的正则表达式

c - 如何从文件中获取字符串并存储在二维字符数组中,并将该二维字符数组与 C 中的字符串进行比较?

image - 如何在 Matlab 中找到二值图像中的所有连通分量?

matlab - 快速傅里叶在matlab中检测钢琴频率

java - 昨天日期的正则表达式模式,格式为 yyyymmdd

python - 使用python查找单词中所有可能重叠的前缀

java - Java中统计字符串出现的次数

在 C 中使用 strcpy 将函数中的单词复制到字符串?