diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-01-20 16:57:19 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-01-20 16:57:19 +0100 |
commit | 2f5b5beb28a3ffe9d12a19b79c453c640cee2f29 (patch) | |
tree | cb30f5a4afaa2923bb787f282ad20b004a408d71 | |
parent | 81fa999540740b5269a349a9e991eb506592ea75 (diff) | |
download | busybox-2f5b5beb28a3ffe9d12a19b79c453c640cee2f29.tar.gz |
grep: fix grep -Fw not respecting the -w option. Closes 5792
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | findutils/grep.c | 37 | ||||
-rwxr-xr-x | testsuite/grep.tests | 12 |
2 files changed, 44 insertions, 5 deletions
diff --git a/findutils/grep.c b/findutils/grep.c index de4fcf5ad..70f3516a5 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -344,10 +344,34 @@ static int grep_file(FILE *file) while (pattern_ptr) { gl = (grep_list_data_t *)pattern_ptr->data; if (FGREP_FLAG) { - found |= (((option_mask32 & OPT_i) - ? strcasestr(line, gl->pattern) - : strstr(line, gl->pattern) - ) != NULL); + char *match; + char *str = line; + opt_f_again: + match = ((option_mask32 & OPT_i) + ? strcasestr(str, gl->pattern) + : strstr(str, gl->pattern) + ); + if (match) { + if (option_mask32 & OPT_x) { + if (match != str) + goto opt_f_not_found; + if (str[strlen(gl->pattern)] != '\0') + goto opt_f_not_found; + } else + if (option_mask32 & OPT_w) { + char c = (match != str) ? match[-1] : ' '; + if (!isalnum(c) && c != '_') { + c = match[strlen(gl->pattern)]; + if (!c || (!isalnum(c) && c != '_')) + goto opt_f_found; + } + str = match + 1; + goto opt_f_again; + } + opt_f_found: + found = 1; + opt_f_not_found: ; + } } else { if (!(gl->flg_mem_alocated_compiled & COMPILED)) { gl->flg_mem_alocated_compiled |= COMPILED; @@ -376,7 +400,8 @@ static int grep_file(FILE *file) if (option_mask32 & OPT_x) { found = (gl->matched_range.rm_so == 0 && line[gl->matched_range.rm_eo] == '\0'); - } else if (!(option_mask32 & OPT_w)) { + } else + if (!(option_mask32 & OPT_w)) { found = 1; } else { char c = ' '; @@ -387,6 +412,8 @@ static int grep_file(FILE *file) if (!c || (!isalnum(c) && c != '_')) found = 1; } +//BUG: "echo foop foo | grep -w foo" should match, but doesn't: +//we bail out on first "mismatch" because it's not a word. } } } diff --git a/testsuite/grep.tests b/testsuite/grep.tests index 006a215e1..4781f2284 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests @@ -115,6 +115,18 @@ testing "grep -v -f EMPTY_FILE" \ "" \ "test\n" +testing "grep -Fw matches only words" \ + "grep -Fw foo input" \ + "" \ + "foop\n" \ + "" + +testing "grep -Fw doesn't stop on 1st mismatch" \ + "grep -Fw foo input" \ + "foop foo\n" \ + "foop foo\n" \ + "" + # testing "test name" "commands" "expected result" "file input" "stdin" # file input will be file called "input" # test can create a file "actual" instead of writing to stdout |