これはあなたのために働くでしょう:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main(void) {
const char tests[2][4] = {"-l4", "-lm"};
const char match[] = "-l[[:digit:]]+";
regex_t rmatch;
if ( regcomp(&rmatch, match, REG_EXTENDED) != 0 ) {
perror("Error compiling regex");
return EXIT_FAILURE;
}
for ( int i = 0; i < 2; ++i ) {
if ( regexec(&rmatch, tests[i], 0, NULL, 0) != 0 ) {
printf("No match for '%s'.\n", tests[i]);
} else {
printf("Matched '%s'.\n", tests[i]);
}
}
return 0;
}
出力:
paul@local:~/src/c/scratch$ ./regex
Matched '-l4'.
No match for '-lm'.
paul@local:~/src/c/scratch$
編集:投稿したコードには、いくつかの問題があります。
この行:
if(regcomp(®ex,"-l[[digit:]]+",0)){
次のようにする必要があります。
if( regcomp(®ex, "-l[[:digit:]]+", REG_EXTENDED) ) {
拡張正規表現を使用しているためです。この行を変更すると、パターンが正常に一致します。
あなたのセグメンテーション違反は、実際には正規表現とは何の関係もなく、これを呼び出すことから来ています:
fclose(f);
ファイルを正常に開いたことがない実行パス上にある場合。変更する必要があります:
FILE *f;
に:
FILE *f = NULL;
そして変更:
fclose(f);
に:
if ( f ) {
fclose(f);
}
gdb に慣れ親しむことは、これらのことを自分で追跡できるようになるための長い道のりです。
以下は、動作する独自のコードの修正版で、いくつかの基本的なエラー チェックが含まれています。
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
void reversetext(FILE * f);
int main(int argc, char *argv[]) {
regex_t rmatch;
FILE *f = NULL;
int c;
if ( argc < 2 ) {
printf("You need to enter at least one command line argument.\n");
return EXIT_FAILURE;
}
if ( regcomp(&rmatch, "-l[[:digit:]]+", REG_EXTENDED) ) {
printf("Could not compile regex.\n");
return EXIT_FAILURE;
}
if ( strcmp(argv[1], "-r") == 0 && argc > 2 ) {
printf("argv[1] is -r\n");
if ( (f = fopen(argv[2], "r")) == NULL ) {
fprintf(stderr, "Couldn't open file %s\n", argv[2]);
return EXIT_FAILURE;
}
reversetext(f);
} else if (regexec(&rmatch, argv[1], 0, NULL, 0) == 0) {
printf("Matched '%s' to regex\n", argv[1]);
} else {
if ( (f = fopen(argv[1], "r")) == NULL ) {
fprintf(stderr, "Couldn't open file %s\n", argv[1]);
return EXIT_FAILURE;
}
while ( (c = getc(f)) != EOF) {
printf("%c", c);
}
}
if ( f ) {
fclose(f);
}
}
void reversetext(FILE * f) {
int c = getc(f);
if (c == EOF) {
return;
}
reversetext(f);
printf("%c", c);
}
出力:
paul@local:~/src/c/scratch$ ./regex2 -l4
Matched '-l4' to regex
paul@local:~/src/c/scratch$ ./regex2 -r fakefile
argv[1] is -r
Couldn't open file fakefile
paul@local:~/src/c/scratch$ ./regex2 -tribbles
Couldn't open file -tribbles
paul@local:~/src/c/scratch$ ./regex2 testfile
This is a test.
paul@local:~/src/c/scratch$ ./regex2 -r testfile
argv[1] is -r
.tset a si sihTpaul@local:~/src/c/scratch$
あなたが and を使用している場合getc()
、友人はint
s ではなくchar
s を使用することに注意してください。これは、保存できるようにするために必要EOF
です。
編集 2: コメントの質問に従って、サブグループ、この場合は一致の数値部分を一致させるために 4 つのことを行う必要があります。
タイプ の配列を設定しregmatch_t
ます。最初の要素は正規表現全体に一致するため、少なくとも 2 つの要素が必要です。また、1 つのサブグループに対して少なくとも 1 秒必要です。以下のコードでは、次を追加しました。
#define MAX_MATCHES 10
regmatch_t m_group[MAX_MATCHES];
抽出したい正規表現の部分を括弧で囲みます。以下のコードでは、次のように変更しました。
"-l[[:digit:]]+"
に:
"-l([[:digit:]]+)"
配列を呼び出すときに、サイズとともにregmatch_t
配列を渡します。regexec()
以下のコードでは、次のように変更しました。
} else if (regexec(&rmatch, argv[1], 0, NULL, 0) == 0) {
に:
} else if (regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0) {
配列を循環し、各一致を処理します。配列要素のrm_so
メンバーが でない場合は常に、一致があります。ここで行っているのは、それらをバッファーにコピーして出力することだけです。regmatch_t
-1
} else if ( regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0 ) {
printf("Matched '%s' to regex\n", argv[1]);
for ( int i = 0; i < MAX_MATCHES && m_group[i].rm_so != -1; ++i ) {
char buffer[1000] = {0};
char * match_start = &argv[1][m_group[i].rm_so];
size_t match_size = m_group[i].rm_eo - m_group[i].rm_so;
size_t match_len = match_size > 999 ? 999 : match_size;
strncpy(buffer, match_start, match_len);
printf("Matched group %d was '%s'\n", i, buffer);
}
}
更新されたコードは次のとおりです。
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#define MAX_MATCHES 10
void reversetext(FILE * f);
int main(int argc, char *argv[]) {
regex_t rmatch;
regmatch_t m_group[MAX_MATCHES];
FILE *f = NULL;
int c;
if ( argc < 2 ) {
printf("You need to enter at least one command line argument.\n");
return EXIT_FAILURE;
}
if ( regcomp(&rmatch, "-l([[:digit:]])+", REG_EXTENDED) ) {
printf("Could not compile regex.\n");
return EXIT_FAILURE;
}
if ( strcmp(argv[1], "-r") == 0 && argc > 2) {
printf("argv[1] is -r\n");
if ( (f = fopen(argv[2], "r")) == NULL ) {
fprintf(stderr, "Couldn't open file %s\n", argv[2]);
return EXIT_FAILURE;
}
reversetext(f);
} else if ( regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0 ) {
printf("Matched '%s' to regex\n", argv[1]);
for ( int i = 0; i < MAX_MATCHES && m_group[i].rm_so && ; ++i ) {
char buffer[1000] = {0};
char * match_start = &argv[1][m_group[i].rm_so];
size_t match_size = m_group[i].rm_eo - m_group[i].rm_so;
size_t match_len = match_size > 999 ? 999 : match_size;
strncpy(buffer, match_start, match_len);
printf("Matched group %d was '%s'\n", i, buffer);
}
} else {
if ( (f = fopen(argv[1], "r")) == NULL ) {
fprintf(stderr, "Couldn't open file %s\n", argv[1]);
return EXIT_FAILURE;
}
while ( (c = getc(f)) != EOF) {
printf("%c", c);
}
}
if ( f ) {
fclose(f);
}
}
void reversetext(FILE * f) {
int c = getc(f);
if (c == EOF) {
return;
}
reversetext(f);
printf("%c", c);
}
出力:
paul@local:~/src/c/scratch$ ./regex2 -l4
Matched '-l4' to regex
Matched group 0 was '-l4'
Matched group 1 was '4'
paul@local:~/src/c/scratch$