“模式匹配”和C中的提取

时间:2013-03-03 09:30:42

标签: c pattern-matching

我需要解析很多文件名(我猜是多达250000),包括路径,并从中提取一些部分。

以下是一个例子:

原文:/my/complete/path/to/80/01/a9/1d.pdf

需要:8001a91d

我正在寻找的“模式”将始终以“/ 8”开头。我需要提取的部分形成一个8位十六进制数字的字符串。

我的想法如下(简化为演示):

/* original argument */
char *path = "/my/complete/path/to/80/01/a9/1d.pdf";

/* pointer to substring */
char *begin = NULL;

/* final char array to be build */
char *hex = (char*)malloc(9);

/* find "pattern" */
begin = strstr(path, "/8");
if(begin == NULL)
    return 1;

/* jump to first needed character */
begin++;

/* copy the needed characters to target char array */
strncpy(hex,   begin,   2);
strncpy(hex+2, begin+3, 2);
strncpy(hex+4, begin+6, 2);
strncpy(hex+6, begin+9, 2);
strncpy(hex+8, "\0",    1);     

/* print final char array */
printf("%s\n", hex);

这很有效。我只是觉得这不是最聪明的方式。并且可能有一些陷阱我不认为自己。

那么,是否有人建议使用这种指针移位方式可能会有什么危险?你认为会有什么改进?

C是否提供了像s|/(8.)/(..)/(..)/(..)\.|\1\2\3\4|这样的功能?如果我记得有些脚本语言有这样的功能;如果你知道我的意思。

3 个答案:

答案 0 :(得分:2)

C本身并不提供此功能,但您可以使用POSIX正则表达式。它是一个功能齐全的正则表达式库。但对于像你这样简单的模式,这可能是最好的方式。

BTW,首选memcpystrncpy。很少有人知道strncpy有什么好处。而且我不是其中之一。

答案 1 :(得分:0)

在仅仅匹配/8./../../..的简单情况下,我个人自己去寻找strstr()解决方案(不需要外部依赖)。如果规则变得更多,你可以尝试词法分析器(flex和朋友),它们支持正则表达式。

在你的情况下是这样的:

h2           [0-9A-Fa-f]{2}
mymatch      (/{h2}){4}

可行。您必须通过副作用将缓冲区设置为匹配,但词法分析器通常会返回标记标识符。

无论如何,你在没有依赖关系的情况下获得了正则表达式的强大功能,但却牺牲了生成的(读取:不可读)代码。

答案 2 :(得分:0)

/* original argument */
char *path = "/my/complete/path/to/80/01/a9/1d.pdf";
char *begin;
char hex[9];
size_t len;

/* find "pattern" */
begin = strstr(path, "/8");
if (!begin) return 1;

// sanity check
len = strlen(begin);
if (len < 12) return 2; 

   // more sanity
if (begin[3] != '/' || begin[6] != '/' ||  begin[9] != '/' ) return 3;

memcpy(hex,   begin+1, 2);
memcpy(hex+2, begin+4, 2);
memcpy(hex+4, begin+7, 2);
memcpy(hex+6, begin+10, 2);
       hex[8] = 0;     

   // For additional sanity, you could check for valid hex characters here
/* print final char array */
printf("%s\n", hex);