Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 8873)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 8874)
@@ -8,4 +8,5 @@
 import java.util.Collection;
 import java.util.EnumSet;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -54,4 +55,8 @@
         default: throw new AssertionError();
         }
+    }
+
+    public static Condition createRegexpKeyRegexpValueCondition(String k, String v, Op op) {
+        return new RegexpKeyValueRegexpCondition(k, v, op);
     }
 
@@ -287,14 +292,38 @@
         }
 
+        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) {
-            final String value = env.osm.get(k);
             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;
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 8873)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 8874)
@@ -755,9 +755,14 @@
     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)
@@ -807,5 +812,7 @@
             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); }
 }
 
Index: /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy	(revision 8873)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/KeyValueConditionTest.groovy	(revision 8874)
@@ -1,6 +1,4 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.mappaint.mapcss;
-
-import static org.junit.Assert.*
 
 import org.junit.*
@@ -9,4 +7,5 @@
 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
@@ -14,4 +13,5 @@
 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
 
 
@@ -86,3 +86,18 @@
         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")))
+    }
 }
