Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java	(revision 15302)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Functions.java	(working copy)
@@ -9,9 +9,11 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map.Entry;
 import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.zip.CRC32;

 import org.openstreetmap.josm.data.coor.LatLon;
@@ -386,6 +388,60 @@
     }

     /**
+     * Get keys that follow a regex
+     * @param env the environment
+     * @param key_regex the pattern that the key must match
+     * @return the values for the keys that match the pattern
+     * @see Functions#tag_regex(Environment, String, String)
+     * @since xxx
+     */
+    public static List<String> tag_regex(final Environment env, String key_regex) { // NO_UCD (unused code)
+        return tag_regex(env, key_regex, "");
+    }
+
+    /**
+     * Get keys that follow a regex
+     * @param env the environment
+     * @param key_regex the pattern that the key must match
+     * @return the values for the keys that match the pattern
+     * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")
+     * @see Pattern#CASE_INSENSITIVE
+     * @see Pattern#DOTALL
+     * @see Pattern#MULTILINE
+     * @since xxx
+     */
+    public static List<String> tag_regex(final Environment env, String key_regex, String flags) { // NO_UCD (unused code)
+        int f = parse_regex_flags(flags);
+        Pattern compiled = Pattern.compile(key_regex, f);
+        return env.osm.getKeys().entrySet().stream()
+                .filter(object -> compiled.matcher(object.getKey()).find())
+                .map(Entry::getValue).collect(Collectors.toList());
+    }
+
+    /**
+     * Parse flags for regex usage. Shouldn't be used in mapcss
+     * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")
+     * @see Pattern#CASE_INSENSITIVE
+     * @see Pattern#DOTALL
+     * @see Pattern#MULTILINE
+     * @return An int that can be used by a {@link Pattern} object
+     * @since xxx
+     */
+    private static final int parse_regex_flags(String flags) {
+        int f = 0;
+        if (flags.contains("i")) {
+            f |= Pattern.CASE_INSENSITIVE;
+        }
+        if (flags.contains("s")) {
+            f |= Pattern.DOTALL;
+        }
+        if (flags.contains("m")) {
+            f |= Pattern.MULTILINE;
+        }
+        return f;
+    }
+
+    /**
      * Gets the first non-null value of the key {@code key} from the object's parent(s).
      * @param env the environment
      * @param key the OSM key
@@ -724,16 +799,7 @@
      * @since 5699
      */
     public static boolean regexp_test(String pattern, String target, String flags) { // NO_UCD (unused code)
-        int f = 0;
-        if (flags.contains("i")) {
-            f |= Pattern.CASE_INSENSITIVE;
-        }
-        if (flags.contains("s")) {
-            f |= Pattern.DOTALL;
-        }
-        if (flags.contains("m")) {
-            f |= Pattern.MULTILINE;
-        }
+        int f = parse_regex_flags(flags);
         return Pattern.compile(pattern, f).matcher(target).matches();
     }

@@ -751,16 +817,7 @@
      * @since 5701
      */
     public static List<String> regexp_match(String pattern, String target, String flags) { // NO_UCD (unused code)
-        int f = 0;
-        if (flags.contains("i")) {
-            f |= Pattern.CASE_INSENSITIVE;
-        }
-        if (flags.contains("s")) {
-            f |= Pattern.DOTALL;
-        }
-        if (flags.contains("m")) {
-            f |= Pattern.MULTILINE;
-        }
+        int f = parse_regex_flags(flags);
         return Utils.getMatches(Pattern.compile(pattern, f).matcher(target));
     }

Index: test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java	(revision 15302)
+++ test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java	(working copy)
@@ -12,6 +12,7 @@
 import java.util.Arrays;
 import java.util.List;

+import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
 import org.openstreetmap.josm.TestUtils;
@@ -262,7 +263,41 @@
         assertFalse(c2.applies(new Environment(w2)));
     }

+    /**
+     * Make certain that getting tags by regex works
+     * @throws Exception if there is an assert error (or another error)
+     */
     @Test
+    public void testTagRegex() throws Exception {
+        DataSet ds = new DataSet();
+        Way way1 = TestUtils.newWay("old_ref=A1 ref=A2", new Node(new LatLon(1, 1)), new Node(new LatLon(2, 2)));
+        for (Node node : way1.getNodes()) {
+            ds.addPrimitive(node);
+        }
+        ds.addPrimitive(way1);
+
+        tagRegex(way1, "way[ref][count(tag_regex(\"ref\")) > 1] {}", new Boolean[] {true, false, false, true, false});
+        way1.keySet().stream().forEach(key -> way1.put(key, null));
+        way1.put("old_ref", "A1");
+        way1.put("ref", "A2");
+        tagRegex(way1, "way[ref][count(tag_regex(\"ref\", \"i\")) > 1] {}", new Boolean[] {true, false, false, true, true});
+    }
+
+    private void tagRegex(Way way, String parserString, Boolean[] expected) throws Exception {
+        Selector selector = getParser(parserString).selector();
+        Assert.assertEquals(expected[0], selector.matches(new Environment(way)));
+        way.put("old_ref", null);
+        Assert.assertEquals(expected[1], selector.matches(new Environment(way)));
+        way.put("no_match_tag", "false");
+        Assert.assertEquals(expected[2], selector.matches(new Environment(way)));
+        way.put("old_ref", "A22");
+        Assert.assertEquals(expected[3], selector.matches(new Environment(way)));
+        way.put("old_ref", null);
+        way.put("OLD_REF", "A23");
+        Assert.assertEquals(expected[4], selector.matches(new Environment(way)));
+    }
+
+    @Test
     public void testParentTag() throws Exception {
         Selector c1 = getParser("way[foo] > node[tag(\"foo\")=parent_tag(\"foo\")] {}").child_selector();
         DataSet ds = new DataSet();
