diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-29 20:58:53 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-29 20:58:53 +0000 |
commit | 51937534fb6ae25b4197ac03635bb09a405957ba (patch) | |
tree | 2d623f9e65f1429349dc38e16a23ea52722d0790 | |
parent | 266bc17690cd8e98bf30514a19f95891b6ccd1d3 (diff) | |
download | busybox-w32-51937534fb6ae25b4197ac03635bb09a405957ba.tar.gz busybox-w32-51937534fb6ae25b4197ac03635bb09a405957ba.tar.bz2 busybox-w32-51937534fb6ae25b4197ac03635bb09a405957ba.zip |
grep: implement -o option. Patch by Jac Goudsmit.
-rw-r--r-- | findutils/grep.c | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/findutils/grep.c b/findutils/grep.c index ebd9596e0..f301b535d 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -14,7 +14,10 @@ | |||
14 | * 2004,2006 (C) Vladimir Oleynik <dzo@simtreas.ru> - | 14 | * 2004,2006 (C) Vladimir Oleynik <dzo@simtreas.ru> - |
15 | * correction "-e pattern1 -e pattern2" logic and more optimizations. | 15 | * correction "-e pattern1 -e pattern2" logic and more optimizations. |
16 | * precompiled regex | 16 | * precompiled regex |
17 | */ | 17 | */ |
18 | /* | ||
19 | * (C) 2006 Jac Goudsmit added -o option | ||
20 | */ | ||
18 | 21 | ||
19 | #include "busybox.h" | 22 | #include "busybox.h" |
20 | #include "xregex.h" | 23 | #include "xregex.h" |
@@ -22,7 +25,7 @@ | |||
22 | 25 | ||
23 | /* options */ | 26 | /* options */ |
24 | static unsigned long opt; | 27 | static unsigned long opt; |
25 | #define GREP_OPTS "lnqvscFiHhe:f:L" | 28 | #define GREP_OPTS "lnqvscFiHhe:f:Lo" |
26 | #define GREP_OPT_l (1<<0) | 29 | #define GREP_OPT_l (1<<0) |
27 | #define PRINT_FILES_WITH_MATCHES (opt & GREP_OPT_l) | 30 | #define PRINT_FILES_WITH_MATCHES (opt & GREP_OPT_l) |
28 | #define GREP_OPT_n (1<<1) | 31 | #define GREP_OPT_n (1<<1) |
@@ -44,19 +47,20 @@ static invert_search_t invert_search; | |||
44 | #define GREP_OPT_e (1<<10) | 47 | #define GREP_OPT_e (1<<10) |
45 | #define GREP_OPT_f (1<<11) | 48 | #define GREP_OPT_f (1<<11) |
46 | #define GREP_OPT_L (1<<12) | 49 | #define GREP_OPT_L (1<<12) |
47 | #define PRINT_FILES_WITHOUT_MATCHES ((opt & GREP_OPT_L) != 0) | 50 | #define PRINT_FILES_WITHOUT_MATCHES (opt & GREP_OPT_L) |
51 | #define GREP_OPT_o (1<<13) | ||
48 | #if ENABLE_FEATURE_GREP_CONTEXT | 52 | #if ENABLE_FEATURE_GREP_CONTEXT |
49 | #define GREP_OPT_CONTEXT "A:B:C:" | 53 | #define GREP_OPT_CONTEXT "A:B:C:" |
50 | #define GREP_OPT_A (1<<13) | 54 | #define GREP_OPT_A (1<<14) |
51 | #define GREP_OPT_B (1<<14) | 55 | #define GREP_OPT_B (1<<15) |
52 | #define GREP_OPT_C (1<<15) | 56 | #define GREP_OPT_C (1<<16) |
53 | #define GREP_OPT_E (1<<16) | 57 | #define GREP_OPT_E (1<<17) |
54 | #else | 58 | #else |
55 | #define GREP_OPT_CONTEXT "" | 59 | #define GREP_OPT_CONTEXT "" |
56 | #define GREP_OPT_A (0) | 60 | #define GREP_OPT_A 0 |
57 | #define GREP_OPT_B (0) | 61 | #define GREP_OPT_B 0 |
58 | #define GREP_OPT_C (0) | 62 | #define GREP_OPT_C 0 |
59 | #define GREP_OPT_E (1<<13) | 63 | #define GREP_OPT_E (1<<14) |
60 | #endif | 64 | #endif |
61 | #if ENABLE_FEATURE_GREP_EGREP_ALIAS | 65 | #if ENABLE_FEATURE_GREP_EGREP_ALIAS |
62 | # define OPT_EGREP "E" | 66 | # define OPT_EGREP "E" |
@@ -100,7 +104,9 @@ static void print_line(const char *line, int linenum, char decoration) | |||
100 | printf("%s%c", cur_file, decoration); | 104 | printf("%s%c", cur_file, decoration); |
101 | if (PRINT_LINE_NUM) | 105 | if (PRINT_LINE_NUM) |
102 | printf("%i%c", linenum, decoration); | 106 | printf("%i%c", linenum, decoration); |
103 | puts(line); | 107 | /* Emulate weird GNU grep behavior with -ov */ |
108 | if ((opt & (GREP_OPT_v+GREP_OPT_o)) != (GREP_OPT_v+GREP_OPT_o)) | ||
109 | puts(line); | ||
104 | } | 110 | } |
105 | 111 | ||
106 | 112 | ||
@@ -110,6 +116,7 @@ static int grep_file(FILE *file) | |||
110 | invert_search_t ret; | 116 | invert_search_t ret; |
111 | int linenum = 0; | 117 | int linenum = 0; |
112 | int nmatches = 0; | 118 | int nmatches = 0; |
119 | regmatch_t regmatch; | ||
113 | #if ENABLE_FEATURE_GREP_CONTEXT | 120 | #if ENABLE_FEATURE_GREP_CONTEXT |
114 | int print_n_lines_after = 0; | 121 | int print_n_lines_after = 0; |
115 | int curpos = 0; /* track where we are in the circular 'before' buffer */ | 122 | int curpos = 0; /* track where we are in the circular 'before' buffer */ |
@@ -137,12 +144,14 @@ static int grep_file(FILE *file) | |||
137 | gl->flg_mem_alocated_compiled |= COMPILED; | 144 | gl->flg_mem_alocated_compiled |= COMPILED; |
138 | xregcomp(&(gl->preg), gl->pattern, reflags); | 145 | xregcomp(&(gl->preg), gl->pattern, reflags); |
139 | } | 146 | } |
140 | ret |= regexec(&(gl->preg), line, 0, NULL, 0) == 0; | 147 | regmatch.rm_so = 0; |
148 | regmatch.rm_eo = 0; | ||
149 | ret |= regexec(&(gl->preg), line, 1, ®match, 0) == 0; | ||
141 | } | 150 | } |
142 | pattern_ptr = pattern_ptr->link; | 151 | pattern_ptr = pattern_ptr->link; |
143 | } /* while (pattern_ptr) */ | 152 | } /* while (pattern_ptr) */ |
144 | 153 | ||
145 | if ((ret ^ invert_search)) { | 154 | if (ret ^ invert_search) { |
146 | 155 | ||
147 | if (PRINT_FILES_WITH_MATCHES || BE_QUIET) | 156 | if (PRINT_FILES_WITH_MATCHES || BE_QUIET) |
148 | free(line); | 157 | free(line); |
@@ -190,7 +199,12 @@ static int grep_file(FILE *file) | |||
190 | /* make a note that we need to print 'after' lines */ | 199 | /* make a note that we need to print 'after' lines */ |
191 | print_n_lines_after = lines_after; | 200 | print_n_lines_after = lines_after; |
192 | #endif | 201 | #endif |
193 | print_line(line, linenum, ':'); | 202 | if (opt & GREP_OPT_o) { |
203 | line[regmatch.rm_eo] = '\0'; | ||
204 | print_line(line + regmatch.rm_so, linenum, ':'); | ||
205 | } else { | ||
206 | print_line(line, linenum, ':'); | ||
207 | } | ||
194 | } | 208 | } |
195 | } | 209 | } |
196 | #if ENABLE_FEATURE_GREP_CONTEXT | 210 | #if ENABLE_FEATURE_GREP_CONTEXT |
@@ -212,7 +226,6 @@ static int grep_file(FILE *file) | |||
212 | free(line); | 226 | free(line); |
213 | } | 227 | } |
214 | 228 | ||
215 | |||
216 | /* special-case file post-processing for options where we don't print line | 229 | /* special-case file post-processing for options where we don't print line |
217 | * matches, just filenames and possibly match counts */ | 230 | * matches, just filenames and possibly match counts */ |
218 | 231 | ||
@@ -284,7 +297,6 @@ int grep_main(int argc, char **argv) | |||
284 | 297 | ||
285 | /* do normal option parsing */ | 298 | /* do normal option parsing */ |
286 | #if ENABLE_FEATURE_GREP_CONTEXT | 299 | #if ENABLE_FEATURE_GREP_CONTEXT |
287 | { | ||
288 | char *junk; | 300 | char *junk; |
289 | char *slines_after; | 301 | char *slines_after; |
290 | char *slines_before; | 302 | char *slines_before; |
@@ -316,13 +328,12 @@ int grep_main(int argc, char **argv) | |||
316 | bb_error_msg_and_die(bb_msg_invalid_arg, slines_before, "-B"); | 328 | bb_error_msg_and_die(bb_msg_invalid_arg, slines_before, "-B"); |
317 | } | 329 | } |
318 | /* sanity checks after parse may be invalid numbers ;-) */ | 330 | /* sanity checks after parse may be invalid numbers ;-) */ |
319 | if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L))) { | 331 | if (opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l|GREP_OPT_L)) { |
320 | opt &= ~GREP_OPT_n; | 332 | opt &= ~GREP_OPT_n; |
321 | lines_before = 0; | 333 | lines_before = 0; |
322 | lines_after = 0; | 334 | lines_after = 0; |
323 | } else if(lines_before > 0) | 335 | } else if(lines_before > 0) |
324 | before_buf = (char **)xzalloc(lines_before * sizeof(char *)); | 336 | before_buf = (char **)xzalloc(lines_before * sizeof(char *)); |
325 | } | ||
326 | #else | 337 | #else |
327 | /* with auto sanity checks */ | 338 | /* with auto sanity checks */ |
328 | bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n"; | 339 | bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n"; |
@@ -348,11 +359,12 @@ int grep_main(int argc, char **argv) | |||
348 | if(ENABLE_FEATURE_GREP_FGREP_ALIAS && bb_applet_name[0] == 'f') | 359 | if(ENABLE_FEATURE_GREP_FGREP_ALIAS && bb_applet_name[0] == 'f') |
349 | opt |= GREP_OPT_F; | 360 | opt |= GREP_OPT_F; |
350 | 361 | ||
362 | if(!(opt & GREP_OPT_o)) | ||
363 | reflags = REG_NOSUB; | ||
364 | |||
351 | if(ENABLE_FEATURE_GREP_EGREP_ALIAS && | 365 | if(ENABLE_FEATURE_GREP_EGREP_ALIAS && |
352 | (bb_applet_name[0] == 'e' || (opt & GREP_OPT_E))) | 366 | (bb_applet_name[0] == 'e' || (opt & GREP_OPT_E))) |
353 | reflags = REG_EXTENDED | REG_NOSUB; | 367 | reflags |= REG_EXTENDED; |
354 | else | ||
355 | reflags = REG_NOSUB; | ||
356 | 368 | ||
357 | if(opt & GREP_OPT_i) | 369 | if(opt & GREP_OPT_i) |
358 | reflags |= REG_ICASE; | 370 | reflags |= REG_ICASE; |