如何在C中使用正则表达式查找文件中的行?
如何在C编程中使用正则表达式? 例如,如果我想在文件中查找一行如何在C中使用正则表达式查找文件中的行?,c,regex,C,Regex,如何在C编程中使用正则表达式? 例如,如果我想在文件中查找一行 DAEMONS=(sysklogd network sshd !netfs !crond) 然后像这样在单独的行中打印每个守护进程 sysklogd network sshd !netfs !crond 这就是我到目前为止所做的 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/typ
DAEMONS=(sysklogd network sshd !netfs !crond)
然后像这样在单独的行中打印每个守护进程
sysklogd
network
sshd
!netfs
!crond
这就是我到目前为止所做的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
#define tofind "[a-z A-Z] $"
int main(){
FILE *fp;
char line[1024];
int retval = 0;
char address[256];
regex_t re;
if(regcomp(&re, tofind, REG_EXTENDED) != 0)
return;
fp = fopen("/etc/rc.conf","r");//this file has this line "DAEMONS=(sysklogd network sshd !netfs !crond)"
while((fgets(line, 1024, fp)) != NULL) {
if((retval = regexec(&re, address, 0, NULL, 0)) == 0)
printf("%s\n", address);
}
}
#包括
#包括
#包括
#包括
#包括
#定义tofind“[a-z a-z]$”
int main(){
文件*fp;
字符行[1024];
int-retval=0;
字符地址[256];
正则表达式;
if(注册表项(&re、tofind、注册表项扩展)!=0)
返回;
fp=fopen(“/etc/rc.conf”,“r”);//此文件有以下行“守护进程=(sysklogd network sshd!netfs!crond)”
while((fgets(第1024行,fp))!=NULL){
if((retval=regexec(&re,address,0,NULL,0))==0)
printf(“%s\n”,地址);
}
}
任何帮助都将不胜感激。您将该行读入
行
,因此您应该将行
传递到regexec()
。您还需要考虑行尾的换行符是否会影响模式。(使用fgets()
是正确的,但请记住它将换行符保留在末尾。)
您还应该执行return-1
(或任何其他非0模256的值)而不是无值的普通返回值。此外,还应检查文件是否已打开;我不得不使用另一个名称,因为在我的机器上没有像/etc/rc.conf这样的文件——MacOS X
这对我很有用:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <regex.h>
#define tofind "[a-z A-Z] $"
int main(int argc, char **argv)
{
FILE *fp;
char line[1024];
int retval = 0;
regex_t re;
//this file has this line "DAEMONS=(sysklogd network sshd !netfs !crond)"
const char *filename = "/etc/rc.conf";
if (argc > 1)
filename = argv[1];
if (regcomp(&re, tofind, REG_EXTENDED) != 0)
{
fprintf(stderr, "Failed to compile regex '%s'\n", tofind);
return EXIT_FAILURE;
}
fp = fopen(filename, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open file %s (%d: %s)\n",
filename, errno, strerror(errno));
return EXIT_FAILURE;
}
while ((fgets(line, 1024, fp)) != NULL)
{
line[strlen(line)-1] = '\0';
if ((retval = regexec(&re, line, 0, NULL, 0)) == 0)
printf("<<%s>>\n", line);
}
return EXIT_SUCCESS;
}
只要按图所示写入,这将与该行匹配。如果在“S
”和“=
”之间,或者在“=
”和“(
”)之间可以有空格,则需要进行适当的修改。我允许使用尾随空格-人们通常很邋遢;但如果他们使用尾随选项卡,则不会选择该行
一旦找到该行,您就必须将其拆分为多个部分。您可以选择使用“捕获”括号功能,或者简单地使用strchr()
来查找开放括号,然后使用合适的技术来分离守护程序名称-我会避免使用strtok()
,可能使用strspn()
或strcspn()
查找单词
#包括
#包括
#包括
#包括
#包括
#包括
#定义tofind“^daemon=\\([^)]*)\\)[\t]*$”
int main(int argc,字符**argv)
{
文件*fp;
字符行[1024];
int-retval=0;
正则表达式;
regmatch_t rm[2];
//此文件有以下行“守护进程=(sysklogd network sshd!netfs!crond)”
const char*filename=“/etc/rc.conf”;
如果(argc>1)
filename=argv[1];
if(注册表项(&re、tofind、注册表项扩展)!=0)
{
fprintf(stderr,“未能编译正则表达式“%s”\n”,tofind);
返回退出失败;
}
fp=fopen(文件名,“r”);
如果(fp==0)
{
fprintf(stderr,“无法打开文件%s(%d:%s)\n)”,文件名,errno,strerror(errno));
返回退出失败;
}
while((fgets(第1024行,fp))!=NULL)
{
行[strlen(行)-1]='\0';
if((retval=regexec(&re,line,2,rm,0))==0)
{
printf(“\n”,第行);
printf(“行:\n”,(int)(rm[0].rm_-eo-rm[0].rm_-so),行+rm[0].rm_-so);
printf(“Text:\n”,(int)(rm[1].rm_eo-rm[1].rm_so),line+rm[1].rm_so);
char*src=line+rm[1].rm_so;
char*end=line+rm[1].rm_eo;
while(srcend)
len=末端-src;
printf(“名称:\n”,(int)len,src);
src+=len;
src+=strspn(src,“”);
}
}
}
返回退出成功;
}
其中包含大量调试代码,但不会花费您很长时间来生成您请求的答案。我得到:
<<DAEMONS=(sysklogd network sshd !netfs !crond)>>
Line: <<DAEMONS=(sysklogd network sshd !netfs !crond)>>
Text: <<sysklogd network sshd !netfs !crond>>
Name: <<sysklogd>>
Name: <<network>>
Name: <<sshd>>
Name: <<!netfs>>
Name: <<!crond>>
行:
正文:
姓名:
姓名:
姓名:
姓名:
姓名:
注意:当你想在正则表达式中使用反斜杠时,你必须在C源代码中写两个反斜杠。只是想补充一点,正则表达式toFind
有缺陷。反正什么也配不上。@Jeff:你确定吗?如图所示,RE查找一个字母,后跟一个空格和行尾,或者两个空格和行尾。这对于解析/etc/rc.conf是否合理是一个问题——然而,RE找到了它所说的想要找到的东西?/etc/rc.conf内容是bla-bla-bla-DAEMONS=(sysklogd-network-sshd!netfs!crond)bla-bla-bla-bla
@Face:OK-那么正则表达式不是您想要的。您需要在问题中显示一个示例行(缩进为代码),并在其下显示希望正则表达式为您找到的部分。正如我在前面的评论中所解释的那样,您输入的正则表达式查找字母字符或空格,然后在行尾加空格。如果这不是你想要的,那么解释一下你是什么。这就形成了你需要的实际正则表达式。@Jonatha:如果我不够清楚的话,很抱歉。我正在尝试将“DAEMONS=(…)”之间的每个单词分开,并以新行打印每个单词。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <regex.h>
#define tofind "^DAEMONS=\\(([^)]*)\\)[ \t]*$"
int main(int argc, char **argv)
{
FILE *fp;
char line[1024];
int retval = 0;
regex_t re;
regmatch_t rm[2];
//this file has this line "DAEMONS=(sysklogd network sshd !netfs !crond)"
const char *filename = "/etc/rc.conf";
if (argc > 1)
filename = argv[1];
if (regcomp(&re, tofind, REG_EXTENDED) != 0)
{
fprintf(stderr, "Failed to compile regex '%s'\n", tofind);
return EXIT_FAILURE;
}
fp = fopen(filename, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open file %s (%d: %s)\n", filename, errno, strerror(errno));
return EXIT_FAILURE;
}
while ((fgets(line, 1024, fp)) != NULL)
{
line[strlen(line)-1] = '\0';
if ((retval = regexec(&re, line, 2, rm, 0)) == 0)
{
printf("<<%s>>\n", line);
printf("Line: <<%.*s>>\n", (int)(rm[0].rm_eo - rm[0].rm_so), line + rm[0].rm_so);
printf("Text: <<%.*s>>\n", (int)(rm[1].rm_eo - rm[1].rm_so), line + rm[1].rm_so);
char *src = line + rm[1].rm_so;
char *end = line + rm[1].rm_eo;
while (src < end)
{
size_t len = strcspn(src, " ");
if (src + len > end)
len = end - src;
printf("Name: <<%.*s>>\n", (int)len, src);
src += len;
src += strspn(src, " ");
}
}
}
return EXIT_SUCCESS;
}
<<DAEMONS=(sysklogd network sshd !netfs !crond)>>
Line: <<DAEMONS=(sysklogd network sshd !netfs !crond)>>
Text: <<sysklogd network sshd !netfs !crond>>
Name: <<sysklogd>>
Name: <<network>>
Name: <<sshd>>
Name: <<!netfs>>
Name: <<!crond>>