From 49cc3cac30c504abdbd2c075928f5711da4066e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Jul 2021 17:53:55 +0200 Subject: [PATCH] hush: optimize ${var/pattern/repl} for trivial patterns function old new delta expand_one_var 2353 2507 +154 Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++++++++ shell/match.c | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 6b910569f..179155f66 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6466,6 +6466,19 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) /* ${var/[/]pattern[/repl]} helpers */ static char *strstr_pattern(char *val, const char *pattern, int *size) { + if (!strpbrk(pattern, "*?[\\")) { + /* Optimization for trivial patterns. + * Testcase for very slow replace (performs about 22k replaces): + * x=:::::::::::::::::::::: + * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} + * echo "${x//:/|}" + */ + char *found = strstr(val, pattern); + if (found) + *size = strlen(pattern); + return found; + } + while (1) { char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF); debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end); diff --git a/shell/match.c b/shell/match.c index ee8abb2db..90f77546d 100644 --- a/shell/match.c +++ b/shell/match.c @@ -64,11 +64,10 @@ char* FAST_FUNC scan_and_match(char *string, const char *pattern, unsigned flags } while (loc != end) { - char c; int r; - c = *loc; if (flags & SCAN_MATCH_LEFT_HALF) { + char c = *loc; *loc = '\0'; r = fnmatch(pattern, string, 0); //bb_error_msg("fnmatch('%s','%s',0):%d", pattern, string, r);