]> git.donarmstrong.com Git - fastq-tools.git/blob - src/fastq-grep.c
man pages
[fastq-tools.git] / src / fastq-grep.c
1
2 /*
3  * This file is part of fastq-tools.
4  *
5  * Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
6  *
7  * fastq-grep :
8  * Regular expression searches of the sequences within a FASTQ file.
9  *
10  */
11
12
13 #include "common.h"
14 #include "parse.h"
15 #include <stdio.h>
16 #include <string.h>
17 #include <getopt.h>
18 #include <zlib.h>
19 #include <pcre.h>
20
21
22 #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
23 #  include <fcntl.h>
24 #  include <io.h>
25 #  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
26 #else
27 #  define SET_BINARY_MODE(file)
28 #endif
29
30
31 static const char* prog_name = "fastq-grep";
32
33
34 void print_help()
35 {
36     fprintf(stdout, 
37 "fastq-grep [OPTION]... PATTERN [FILE]...\n"
38 "Search for PATTERN in the read sequences in each FILE or standard input.\n"
39 "PATTERN, by default, is a perl compatible regular expression.\n\n"
40 "Options:\n"
41 "  -v, --invert-match      select nonmatching entries\n"
42 "  -c, --count             output only the number of matching sequences\n"
43 "  -h, --help              print this message\n"
44 "  -V, --version           output version information and exit\n"
45     );
46 }
47
48 static int invert_flag;
49 static int count_flag;
50
51
52
53 void fastq_grep(FILE* fin, FILE* fout, pcre* re)
54 {
55     int rc;
56     int ovector[3];
57     size_t count = 0;
58
59     fastq_t* fqf = fastq_open(fin);
60     seq_t* seq = fastq_alloc_seq();
61
62     while (fastq_next(fqf, seq)) {
63         rc = pcre_exec(re,          /* pattern */
64                        NULL,        /* extre data */
65                        seq->seq.s,  /* subject */
66                        seq->seq.n,  /* subject length */
67                        0,           /* subject offset */
68                        0,           /* options */
69                        ovector,     /* output vector */
70                        3         ); /* output vector length */
71
72         if ((invert_flag && rc == PCRE_ERROR_NOMATCH) || rc >= 0) {
73             if (count_flag) count++;
74             else            fastq_print(fout, seq);
75         }
76     }
77
78     fastq_free_seq(seq);
79     fastq_close(fqf);
80
81     if (count_flag) fprintf(fout, "%zu\n", count);
82 }
83
84
85
86 int main(int argc, char* argv[])
87 {
88     SET_BINARY_MODE(stdin);
89     SET_BINARY_MODE(stdout);
90
91     const char* pat;
92     pcre* re;
93     const char* pat_error;
94     int pat_error_offset;
95
96     FILE*  fin;
97
98
99     invert_flag  = 0;
100     count_flag   = 0;
101
102     int opt;
103     int opt_idx;
104
105
106     static struct option long_options[] =
107         { 
108           {"invert-match", no_argument, &invert_flag, 1},
109           {"count",        no_argument, &count_flag,  1},
110           {"help",         no_argument, NULL, 'h'},
111           {"version",      no_argument, NULL, 'V'},
112           {0, 0, 0, 0}
113         };
114
115     while (1) {
116         opt = getopt_long(argc, argv, "vchV", long_options, &opt_idx);
117
118         if( opt == -1 ) break;
119
120         switch (opt) {
121             case 0:
122                 if (long_options[opt_idx].flag != 0) break;
123                 if (optarg) {
124                 }
125                 break;
126
127             case 'v':
128                 invert_flag = 1;
129                 break;
130
131             case 'c':
132                 count_flag = 1;
133                 break;
134
135             case 'h':
136                 print_help();
137                 return 0;
138
139             case 'V':
140                 print_version(stdout, prog_name);
141                 return 0;
142
143             case '?':
144                 return 1;
145
146             default:
147                 abort();
148         }
149     }
150
151     if (optind >= argc) {
152         fprintf(stderr, "A pattern must be specified.\n");
153         return 1;
154     }
155
156     pat = argv[optind++];
157     re = pcre_compile( pat, PCRE_CASELESS, &pat_error, &pat_error_offset, NULL );
158
159
160     if (re == NULL) {
161         fprintf(stderr, "Syntax error in PCRE pattern at offset: %d: %s\n",
162                 pat_error_offset, pat_error );
163         return 1;
164     }
165
166
167     if (optind >= argc || (argc - optind == 1 && strcmp(argv[optind],"-") == 0)) {
168         fastq_grep(stdin, stdout, re);
169     }
170     else {
171         for (; optind < argc; optind++) {
172             fin = fopen(argv[optind], "rb");
173             if (fin == NULL) {
174                 fprintf(stderr, "No such file '%s'.\n", argv[optind]);
175                 continue;
176             }
177
178             fastq_grep(fin, stdout, re);
179
180             fclose(fin);
181         }
182     }
183
184     pcre_free(re);
185
186     return 0;
187 }
188
189
190