Strip comments in a shell script
diff --git a/ninja.go b/ninja.go
index 6932e47..48cea9b 100644
--- a/ninja.go
+++ b/ninja.go
@@ -29,6 +29,36 @@
 	}
 }
 
+func stripShellComment(s string) string {
+	if strings.IndexByte(s, '#') < 0 {
+		// Fast path.
+		return s
+	}
+	var escape bool
+	var quote rune
+	for i, c := range s {
+		if quote > 0 {
+			if quote == c && (quote == '\'' || !escape) {
+				quote = 0
+			}
+		} else if !escape {
+			if c == '#' {
+				return s[:i]
+			} else if c == '\'' || c == '"' || c == '`' {
+				quote = c
+			}
+		}
+		if escape {
+			escape = false
+		} else if c == '\\' {
+			escape = true
+		} else {
+			escape = false
+		}
+	}
+	return s
+}
+
 func genShellScript(runners []runner) string {
 	var buf bytes.Buffer
 	for i, r := range runners {
@@ -39,7 +69,8 @@
 				buf.WriteString(" && ")
 			}
 		}
-		cmd := trimLeftSpace(r.cmd)
+		cmd := stripShellComment(r.cmd)
+		cmd = trimLeftSpace(cmd)
 		cmd = strings.Replace(cmd, "\\\n", " ", -1)
 		cmd = strings.TrimRight(cmd, " \t\n;")
 		cmd = strings.Replace(cmd, "$", "$$", -1)
diff --git a/ninja_test.go b/ninja_test.go
new file mode 100644
index 0000000..8bf9717
--- /dev/null
+++ b/ninja_test.go
@@ -0,0 +1,56 @@
+package main
+
+import "testing"
+
+func TestStripShellComment(t *testing.T) {
+	for _, tc := range []struct {
+		in   string
+		want string
+	}{
+		{
+			in:   `foo`,
+			want: `foo`,
+		},
+		{
+			in:   `foo # bar`,
+			want: `foo `,
+		},
+		{
+			in:   `foo '# bar'`,
+			want: `foo '# bar'`,
+		},
+		{
+			in:   `foo '\'# bar'`,
+			want: `foo '\'`,
+		},
+		{
+			in:   `foo "# bar"`,
+			want: `foo "# bar"`,
+		},
+		{
+			in:   `foo "\"# bar"`,
+			want: `foo "\"# bar"`,
+		},
+		{
+			in:   `foo "\\"# bar"`,
+			want: `foo "\\"`,
+		},
+		{
+			in:   "foo `# bar`",
+			want: "foo `# bar`",
+		},
+		{
+			in:   "foo `\\`# bar`",
+			want: "foo `\\`# bar`",
+		},
+		{
+			in:   "foo `\\\\`# bar`",
+			want: "foo `\\\\`",
+		},
+	} {
+		got := stripShellComment(tc.in)
+		if got != tc.want {
+			t.Errorf(`stripShellComment(%q)=%q, want %q`, tc.in, got, tc.want)
+		}
+	}
+}