diff --git a/pyam/str.py b/pyam/str.py index f9bafca46..53a2ba4f7 100644 --- a/pyam/str.py +++ b/pyam/str.py @@ -4,6 +4,8 @@ import pandas as pd from pandas.api.types import is_list_like +REGEXP_CHARACTERS = r".^$+?()[]{}|" + def concat_with_pipe(x, *args, cols=None): """Concatenate a list or pandas.Series using ``|``, drop None or numpy.nan""" @@ -123,21 +125,17 @@ def reduce_hierarchy(x, depth): """ _x = x.split("|") depth = len(_x) + depth - 1 if depth < 0 else depth - return "|".join(_x[0 : (depth + 1)]) + return "|".join(_x[0: (depth + 1)]) def escape_regexp(s): """Escape characters with specific regexp use""" - return ( - str(s) - .replace("|", "\\|") - .replace(".", r"\.") # `.` has to be replaced before `*` - .replace("*", ".*") - .replace("+", r"\+") - .replace("(", r"\(") - .replace(")", r"\)") - .replace("$", "\\$") - ) + s = str(s) + for c in REGEXP_CHARACTERS: + s = s.replace(c, "\\" + c) + # pyam uses `*` as wildcard, replace with `.*` for regex + s = s.replace("*", ".*") + return s def is_str(x): diff --git a/tests/test_utils.py b/tests/test_utils.py index af2e80b82..6b36c8994 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -78,9 +78,13 @@ def test_pattern_match_dot(): assert (obs == [False, True]).all() -def test_pattern_match_brackets(): - data = pd.Series(["foo (bar)", "foo bar"]) - values = ["foo (bar)"] +@pytest.mark.parametrize( + "bracket", ("(bar)", "[bar]", "{2}") +) +def test_pattern_match_brackets(bracket): + s = f"foo {bracket}" + data = pd.Series([s, "foo bar"]) + values = [s] obs = pattern_match(data, values) assert (obs == [True, False]).all()