diff --git a/sh.dol.c b/sh.dol.c
index 22d09e4..68ee959 100644
--- a/sh.dol.c
+++ b/sh.dol.c
@@ -791,6 +791,50 @@ all_dolmcnts_are_0()
     return 1;
 }
 
+/* Unescape the sub of an :s modifier
+ *
+ * start = start of string
+ * delim = delim character
+ * consumed = incremented by the number of characters consumed before finding
+ * 	delim
+ *
+ * Returns the length of the string after unescaping
+ *
+ * Note the characters that start points at will be changed if an escape is
+ * found - those after the escape character will all be shifted to the left.
+ *
+ * \ is always used as the escape character
+ *
+ * e.g. unescnhs("abc/def/", '/', &i) returns 3 and increments i by 3
+ * 	unescnhs("a\/bc/def/", '/', &i) returns 4, increments i by 5 and makes
+ * 		start[0..4] = "a/bc"
+ * 	unescnhs("a\\bc/def/", '/', &i) returns 4, increments i by 5 and makes
+ * 		start[0..4] = "a\bc"
+ */
+static size_t
+unescnhs(Char *nhs, Char delim, size_t *consumed) {
+    /* how far through the string we have got to */
+    size_t i;
+    /* offset is how far behind the output string is compared to the number of
+     * chars we have consumed. every escape makes us one more behind */
+    size_t offset;
+
+    for (i = 0, offset = 0; ; i++) {
+	if (nhs[i] == '\\') {
+	    offset++;
+	    i++;
+	} else if (nhs[i] == delim) {
+	    /* this is the end so we can return */
+	    *consumed += i;
+	    return i - offset;
+	}
+
+	/* place the current char in its right place in the array, allowing
+	 * for any removed escape characters */
+	nhs[i - offset] = nhs[i];
+    }
+}
+
 static void
 setDolp(Char *cp)
 {
@@ -821,15 +865,11 @@ setDolp(Char *cp)
 		break;
 	    }
 	    lhsub = &dolmod.s[++i];
-	    while(dolmod.s[i] != delim && dolmod.s[++i]) {
-		lhlen++;
-	    }
-	    dolmod.s[i] = 0;
+	    lhlen = unescnhs(lhsub, delim, &i);
+	    lhsub[lhlen] = 0;
 	    rhsub = &dolmod.s[++i];
-	    while(dolmod.s[i] != delim && dolmod.s[++i]) {
-		rhlen++;
-	    }
-	    dolmod.s[i] = 0;
+	    rhlen = unescnhs(rhsub, delim, &i);
+	    rhsub[rhlen] = 0;
 
 	    strip(lhsub);
 	    strip(rhsub);
