From 02efce51a9b6a1a88919261c21588c9a15d90221 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Fri, 4 Dec 2020 18:45:08 +0100 Subject: [PATCH] string match: Only import variables for the first matching argument This makes it work the same whether it quits early (with "-q") or not, and it's generally nice to nail this down. See #7495. --- src/builtin_string.cpp | 9 ++++++++- tests/checks/regex-import.fish | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index 203784c95..234a9d1f7 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -833,6 +833,7 @@ class pcre2_matcher_t : public string_matcher_t { const wchar_t *argv0; compiled_regex_t regex; parser_t &parser; + bool imported_vars = false; enum class match_result_t { pcre2_error = -1, @@ -1058,7 +1059,12 @@ class pcre2_matcher_t : public string_matcher_t { PCRE2_SIZE arglen = arg.length(); auto rc = report_match(arg, pcre2_match(regex.code, PCRE2_SPTR(arg.c_str()), arglen, 0, 0, regex.match, nullptr)); - var_importer.import_vars(rc == match_result_t::match); + // We only import variables for the *first matching argument* + bool had_match = false; + if (rc == match_result_t::match && !imported_vars) { + var_importer.import_vars(rc == match_result_t::match); + had_match = true; + } switch (rc) { case match_result_t::pcre2_error: @@ -1100,6 +1106,7 @@ class pcre2_matcher_t : public string_matcher_t { } } + imported_vars |= had_match; return true; } }; diff --git a/tests/checks/regex-import.fish b/tests/checks/regex-import.fish index 9913d3a77..6dca5f31e 100644 --- a/tests/checks/regex-import.fish +++ b/tests/checks/regex-import.fish @@ -13,7 +13,7 @@ printf "%s\n" $words # CHECK: world # Capture multiple variables -echo "hello world" | string match -rq -- '^(?[^ ]+) (?.*)$' +echo "hello world"\n"snello snorld" | string match -rq -- '^(?[^ ]+) (?.*)$' printf "%s\n" $word1 $word2 # CHECK: hello # CHECK: world @@ -35,6 +35,22 @@ printf "%s\n" $punctuation # CHECK: , # CHECK: ! +# Same thing with multiple arguments +set word +set punctuation +printf '%s\n' "hello world, boy!" "shello shorld, shoy!" | string match -a -qr -- '(?[^ .,!;]+)(?[.,!;])?' +echo $word +# CHECK: hello world boy +printf "%s\n" $punctuation +# CHECK: +# CHECK: , +# CHECK: ! + # Verify read-only variables may not be imported echo hello | string match -rq "(?.*)" # CHECKERR: Modification of read-only variable "version" is not allowed + +# Verify that the *first matching argument* is used. +string match -rq '(?b.*)' -- aaa ba ccc be +echo $bee +# CHECK: ba