wonderer
wonderer

Reputation: 3557

Search for a string in a text file and parse that line (Linux, C)

This is "how to parse a config file" question. Basically i have a text file (/etc/myconfig) that has all kind of settings. I need to read that file and search for the string:

wants_return=yes

once I locate that string I need to parse it and return only whatever it is after the equal sign. I've tried using a combinations of fgets and strtok but I'm getting confused here. in any case anyone knows a function that can perform this?

Code is appreciated.

thanks

Upvotes: 0

Views: 5301

Answers (4)

goldPseudo
goldPseudo

Reputation: 5753

From your comment, it looks like you're already getting the appropriate line from the text file using fgets and loading it into a character buffer. You can use strtok to parse the tokens from the line.

If you run it with the string buffer as the first argument, it will return the first token from that string. If you run the same command with the first argument set to NULL it will return subsequent tokens from the same original string.

A quick example of how to retrieve multiple tokens:

#include <stdio.h>
#include <string.h>

int main() {
  char buffer[17]="wants_return=yes";
  char* tok;
  tok = strtok(buffer, "=");
  printf("%s\n", tok); /* tok points to "wants_return" */
  tok = strtok(NULL, "=");
  printf("%s\n", tok); /* tok points to "yes" */
  return 0;
}

For the second strtok call, you can replace the "=" with "" to return everything to the end of the string, instead of breaking off at the next equal sign.

Upvotes: 0

Jonathan Graehl
Jonathan Graehl

Reputation: 9301

This works: (note: I'm unsure if fgets is supposed to include the newline character in the returned string; if it isn't, you can drop the check for it)

#include <stdio.h>

const unsigned MAXLINE=9999;
char const* FCFG="/etc/myconfig";
char const* findkey="wants_return=";


char * skip_ws(char *line)
{
    return line+strspn(line," \t");
}

char * findval(char *line,char const* prefix,int prelen)
{
    char *p;
    p=skip_ws(line);
    if (strncmp(p,prefix,prelen)==0)
        return p+prelen;
    else
        return NULL;
}

char *findval_slow(char *line,char const* prefix)
{
    return findval(line,prefix,strlen(prefix));
}

int main() {
    FILE *fcfg;
    char line[MAXLINE];
    char *p,*pend;
    int findlen;

    findlen=strlen(findkey);

    fcfg=fopen(FCFG,"r");

    while (p=fgets(line,MAXLINE,fcfg)) {
        printf("Looking at %s\n",p);
        if (p=findval(line,findkey,findlen)) {
            pend=p+strlen(p)-1; /* check last char for newline terminator */
            if (*pend=='\n') *pend=0;
            printf("Found %s\n",p); /* process/parse the value */
        }
    }
    return 0;
}

Upvotes: 2

jheddings
jheddings

Reputation: 27573

Here's a quick example using strtok:

const int linelen = 256;
char line[linelen];

FILE* fp = fopen(argv[1], "r");
if (fp == NULL) {
    perror("Error opening file");
} else {
    while (! feof(fp)) {
        if (fgets(line, linelen , fp)) {
            const char* name = strtok(line, "= \r\n");
            const char* value = strtok(NULL, "= \r\n");
            printf("%s => %s\n", name, value);
        }
    }
    fclose (fp);
}

Note, you'll need to put some additional error checking around it, but this works to parse the files I threw at it.

Upvotes: 1

Craig Trader
Craig Trader

Reputation: 15679

With a POSIX shell, I'd use something like:

answer=`egrep 'wants_config[ ]*=' /etc/myconfig | sed 's/^.*=[ ]*//'`

Of course, if you're looking for an answer that uses the C STDIO library, then you really need to review the STDIO documentation.

Upvotes: -1

Related Questions