如何使用正则表达式解析字符串中的键值对?

How can I use regex to parse key:value pairs in a string?

提问人:johndaly69 提问时间:10/22/2023 最后编辑:ddajohndaly69 更新时间:10/23/2023 访问量:77

问:

void parseBuffer(char buffer[]) {
    regex_t regex;
    regmatch_t matches[3];

    // Define the regular expression pattern
    char pattern[] = "([^:]+):[[:space:]]*([^\\r\\n]+)[\\r\\n]*";

    // Compile the regular expression
    if (regcomp(&regex, pattern, REG_EXTENDED) != 0) {
        fprintf(stderr, "Failed to compile regex\n");
        exit(EXIT_FAILURE);
    }

    // Loop through the buffer to find matches
    char *ptr = buffer;
    while (regexec(&regex, ptr, 3, matches, 0) == 0) {
        // Extract key and value using the matched positions
        char key[BUFF_SIZE], value[BUFF_SIZE];
        strncpy(key, ptr + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
        strncpy(value, ptr + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
        key[matches[1].rm_eo - matches[1].rm_so] = '\0';
        value[matches[2].rm_eo - matches[2].rm_so] = '\0';

        // Print or process the key-value pair
        printf("Key: %s, Value: %s\n", key, value);

        // Move the pointer to the next position after the match
        ptr += matches[0].rm_eo;
    }

    // Free the compiled regex
    regfree(&regex);
}

对于此输入:,为什么将键打印为 Length,将值打印为字符串的其余部分?我想打印 2 个不同的键和 2 个不同的值(长度:10 和 Hello:hi)。Length: 10\r\nHello: hi\r\n\r\n"parsebuffer

C 正则表达式 字符串 POSIX-ERE

评论

0赞 Some programmer dude 10/22/2023
有一种说法是,如果你试图用正则表达式解决一个问题,那就意味着你有两个问题要解决。正则表达式非常强大,但也很难编写,几乎不可能调试。对于你的情况,我建议你做一些更简单的事情:首先是一个函数,它拆分换行符(对)上的输入,而不使用正则表达式。然后,它获取每一行并将其传递给第二个函数,该函数在(并修剪前导和尾随空格)上拆分,仍然没有正则表达式。然后你就有了“键”和它的“值”。\r\n:

答:

3赞 Oka 10/22/2023 #1

char pattern[] = "([^:]+):[[:space:]]*([^\\r\\n]+)[\\r\\n]*";

\\r并且不是 CR 和 LF,而是两个转义字符,以及文字和字符。\\n\rn

换句话说,是一个包含 ASCII 字节的字符串。"\\r\\n"5C 72 5C 6E

您希望使用实际 和 字符(ASCII 和 )。'\r''\n'0D0A

char pattern[] = "([^:]+):[[:space:]]*([^\r\n]+)[\r\n]*";

稍微重构了一下:

#include <regex.h>
#include <stdio.h>
#include <stdlib.h>

static void parseBuffer(const char *buffer)
{
    regex_t regex;
    regmatch_t matches[3];

    const char *pattern = "([^:]+):[[:space:]]*([^\r\n]+)[\r\n]*";

    int ec = regcomp(&regex, pattern, REG_EXTENDED);

    if (ec) {
        char error[512];
        regerror(ec, &regex, error, sizeof error);
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }

    size_t offset = 0;

    while (0 == regexec(&regex, buffer + offset, 3, matches, 0)) {
        size_t key_length = matches[1].rm_eo - matches[1].rm_so;
        size_t field_length = matches[2].rm_eo - matches[2].rm_so;

        printf("key[%zu]<%.*s> field[%zu]<%.*s>\n",
                key_length, (int) key_length, buffer + offset + matches[1].rm_so,
                field_length, (int) field_length, buffer + offset + matches[2].rm_so);

        offset += matches[0].rm_eo;
    }

    regfree(&regex);
}

int main(void)
{
    parseBuffer("Length: 10\r\nHello: hi\r\n\r\n");
}
key[6]<Length> field[2]<10>
key[5]<Hello> field[2]<hi>