diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
index 56b5bba..ffbe0af 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
+++ b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
@@ -7,6 +7,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumSet;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.regex.Pattern;
@@ -55,6 +56,10 @@ else if ("index".equalsIgnoreCase(k))
         }
     }
 
+    public static Condition createRegexpKeyRegexpValueCondition(String k, String v, Op op) {
+        return new RegexpKeyValueRegexpCondition(k, v, op);
+    }
+
     public static Condition createKeyCondition(String k, boolean not, KeyMatchType matchType, Context context) {
         switch (context) {
         case PRIMITIVE:
@@ -286,19 +291,43 @@ public KeyValueRegexpCondition(String k, String v, Op op, boolean considerValAsK
             this.pattern = Pattern.compile(v);
         }
 
-        @Override
-        public boolean applies(Environment env) {
+        protected boolean matches(Environment env) {
             final String value = env.osm.get(k);
+            return value != null && pattern.matcher(value).find();
+        }
+
+        @Override
+        public boolean applies(Environment env) {
             if (Op.REGEX.equals(op)) {
-                return value != null && pattern.matcher(value).find();
+                return matches(env);
             } else if (Op.NREGEX.equals(op)) {
-                return value == null || !pattern.matcher(value).find();
+                return !matches(env);
             } else {
                 throw new IllegalStateException();
             }
         }
     }
 
+    public static class RegexpKeyValueRegexpCondition extends KeyValueRegexpCondition {
+
+        public final Pattern keyPattern;
+
+        public RegexpKeyValueRegexpCondition(String k, String v, Op op) {
+            super(k, v, op, false);
+            this.keyPattern = Pattern.compile(k);
+        }
+
+        @Override
+        protected boolean matches(Environment env) {
+            for (Map.Entry<String,String> kv: env.osm.getKeys().entrySet()) {
+                if (keyPattern.matcher(kv.getKey()).find() && pattern.matcher(kv.getValue()).find()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     public static class RoleCondition extends Condition {
         public final String role;
         public final Op op;
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
index d9e4f01..3bd4370 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
+++ b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
@@ -754,11 +754,16 @@ Condition simple_key_value_condition(Context context) :
     String val;
     float f;
     int i;
+    Condition.KeyMatchType matchType = null;;
     Condition.Op op;
     boolean considerValAsKey = false;
 }
 {
-    key=tag_key() s()
+    (
+        key = regex() s() { matchType = Condition.KeyMatchType.REGEX; }
+    |
+        key=tag_key() s()
+    )
     (
         LOOKAHEAD(3)
             (
@@ -806,7 +811,9 @@ Condition simple_key_value_condition(Context context) :
             s()
             f=float_() { val=Float.toString(f); }
     )
-    { return Condition.createKeyValueCondition(key, val, op, context, considerValAsKey); }
+    { return Condition.KeyMatchType.REGEX == matchType
+            ? Condition.createRegexpKeyRegexpValueCondition(key, val, op)
+            : Condition.createKeyValueCondition(key, val, op, context, considerValAsKey); }
 }
 
 Condition class_or_pseudoclass(Context context) :
diff --git a/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy b/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy
index d025e94..675a623 100644
--- a/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy
+++ b/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy
@@ -1,18 +1,18 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.mappaint.mapcss;
 
-import static org.junit.Assert.*
-
 import org.junit.*
 import org.openstreetmap.josm.JOSMFixture
 import org.openstreetmap.josm.data.coor.LatLon
 import org.openstreetmap.josm.data.osm.DataSet
 import org.openstreetmap.josm.data.osm.Node
+import org.openstreetmap.josm.data.osm.OsmUtils
 import org.openstreetmap.josm.data.osm.Relation
 import org.openstreetmap.josm.data.osm.RelationMember
 import org.openstreetmap.josm.gui.mappaint.Environment
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op
+import org.openstreetmap.josm.gui.mappaint.mapcss.parsergen.MapCSSParser
 
 
 class KeyValueConditionTest {
@@ -85,4 +85,19 @@ class KeyValueConditionTest {
         cond = Condition.createKeyValueCondition("role", "another_role", Op.NEQ, Context.LINK, false)
         assert cond.applies(e)
     }
+
+    @Test
+    public void testKeyRegexValueRegex() throws Exception {
+        def selPos = new MapCSSParser(new StringReader("*[/^source/ =~ /.*,.*/]")).selector()
+        def selNeg = new MapCSSParser(new StringReader("*[/^source/ !~ /.*,.*/]")).selector()
+        assert !selPos.matches(new Environment(OsmUtils.createPrimitive("way foo=bar")))
+        assert selPos.matches(new Environment(OsmUtils.createPrimitive("way source=1,2")))
+        assert selPos.matches(new Environment(OsmUtils.createPrimitive("way source_foo_bar=1,2")))
+        assert !selPos.matches(new Environment(OsmUtils.createPrimitive("way source=1")))
+        assert !selPos.matches(new Environment(OsmUtils.createPrimitive("way source=1")))
+        assert !selNeg.matches(new Environment(OsmUtils.createPrimitive("way source=1,2")))
+        assert !selNeg.matches(new Environment(OsmUtils.createPrimitive("way foo=bar source=1,2")))
+        assert selNeg.matches(new Environment(OsmUtils.createPrimitive("way foo=bar source=baz")))
+        assert selNeg.matches(new Environment(OsmUtils.createPrimitive("way foo=bar src=1,2")))
+    }
 }
