[git commit] grep: fix grep -Fw not respecting the -w option. Closes 5792

Denys Vlasenko vda.linux at googlemail.com
Sun Jan 20 15:57:19 UTC 2013


commit: http://git.busybox.net/busybox/commit/?id=2f5b5beb28a3ffe9d12a19b79c453c640cee2f29
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 findutils/grep.c     |   37 ++++++++++++++++++++++++++++++++-----
 testsuite/grep.tests |   12 ++++++++++++
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/findutils/grep.c b/findutils/grep.c
index de4fcf5..70f3516 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 006a215..4781f22 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


More information about the busybox-cvs mailing list