【问题标题】:How to recognize token with quote inside of double quotes如何在双引号内识别带有引号的标记
【发布时间】:2015-03-12 01:26:44
【问题描述】:

是否有任何库方法或普遍认可的方法来识别双引号内带有引号的标记,同时仍将不带双引号的单引号识别为标记?

例如,字符串:"Bill's Pot" 'Roast' 应导致标记:

Bill's Pot
Roast

【问题讨论】:

  • 您可以尝试使用正则表达式,尽管示例字符串没有明显的问题,所以我不明白您的问题是什么?只需捕获两个 " 字符之间的每个字符?
  • @iharob 抱歉,换行符显示不正确
  • 没有一个标准函数可以解释这样的字符串。还有,总是,“你如何将单引号和双引号放入单个标记”的问题?你是使用双引号(所以""在被双引号包围的字符串中间映射到双引号的单个实例),还是使用另一个转义字符(经典的反斜杠,``)。等等。这样的决定是可以实现的,但是没有专门处理这种解析的 C 标准或 POSIX 标准函数。
  • 一次处理输入一个char,在 4 种状态之一之间移动:空格、单词、“”短语和 '' 短语。
  • 如果您在进行手动解析并且' 字符串也应该能够包含" 字符,那么您可以只查找任一引号,记住是哪个引号,然后扫描对于相同的引号(例如strchr(),假设字符串以空结尾以使其对格式错误的输入安全)。使用 "' 字符串的通用代码很容易。反斜杠转义和不希望字符串中的换行等功能需要更复杂的代码。

标签: c token


【解决方案1】:

没有专门的库函数来执行此操作,但有一些库函数可以帮助您自己执行此操作,例如 strchr 以获取指向特定字符串中您选择的字符的指针,如果它存在,并且isspace 检测未引用字符串的空格字符,尽管isspace 也取决于语言环境。如果您只想删除“C”语言环境中定义的空格字符,只需使用带有第二个参数" \f\n\r\t\v"strspn,而不是重复调用isspace 的循环(注意开头的空格字符那个字符串)。

这是解析示例字符串的一种方法,其中包含允许 C 样式反斜杠转义以允许嵌入引号的附加规则。请注意,它只检测由空格字符分隔的字符串的开头和结尾,这意味着它实际上不会替换转义的引号或做任何其他事情:

char str[] = "\"Bill's Pot\" 'Roast'";
char *start;
char *end;

start = str;
while (*start) {
    // Skip leading spaces.
    while (isspace(*start))
        ++start;

    // Double-quoted string with backslash escapes.
    if (*start == '"') {
        end = strchr(++start, '"');
        while (end != NULL && *end == '"' && end[-1] == '\\')
            end = strchr(++end, '"');
        if (end == NULL || *end == '\0') {
            fprintf(stderr, "Unterminated double-quoted string -- %s\n", --start);
            break;
        }
    }

    // Single-quoted string with backslash escapes.
    else if (*start == '\'') {
        end = strchr(++start, '\'');
        while (end != NULL && *end == '\'' && end[-1] == '\\')
            end = strchr(++end, '\'');
        if (end == NULL || *end == '\0') {
            fprintf(stderr, "Unterminated single-quoted string -- %s\n", --start);
            break;
        }
    }

    // Unquoted (space-delimited) string.
    else if (*start != '\0') {
        end = start + 1;
        while (*end != '\0' && !isspace(*end))
            ++end;
    }

    // Empty string.
    else
        end = start;

    printf("%.*s\n", end - start, start);

    // Quotes must be skipped before continuing parsing.
    if (*end == '\'' || *end == '"')
      ++end;

    // Get ready to start the next round of parsing.
    start = end;
}

您也可以避免使用字符串库函数,而只需进行自己的字符串解析。这使您可以灵活地处理Bill"'s Pot" 形式的字符串之类的事情。应该是一串Bill's Pot 还是两串Bill 's Pot?存在 alternative methodsescape quotation marks 甚至 other ways to delimit strings in addition to single and double quotation marks 以及引用规则 à la POSIX sh 允许您在字符串中嵌入换行符,这意味着开始引号和结束引号位于两个不同的行上,这C 禁止。在后一种情况下,仅 C 字符串函数是不够的,因为您需要一个状态变量来指示您在单引号或双引号字符串中。这应该让您了解@JonathanLeffler 在他的评论中的意思;有这么多不同的报价规则!希望我提供的代码能让您了解如何去做您想做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 2011-04-19
    • 2018-06-13
    • 2022-11-17
    • 1970-01-01
    相关资源
    最近更新 更多