summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c13
-rw-r--r--shell/match.c3
2 files changed, 14 insertions, 2 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 6b91056..179155f 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 ee8abb2..90f7754 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);