diff options
-rw-r--r-- | editors/sed.c | 41 | ||||
-rwxr-xr-x | testsuite/sed.tests | 4 |
2 files changed, 33 insertions, 12 deletions
diff --git a/editors/sed.c b/editors/sed.c index c434eee1b..f7f22f750 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -1175,21 +1175,38 @@ restart: } /* It is possible to have a command line argument with embedded - newlines. This counts as multiple command lines. */ + * newlines. This counts as multiple command lines. + * However, newline can be escaped: 's/e/z\<newline>z/' + * We check for this. + */ static void add_cmd_block(char *cmdstr) { - int go = 1; - char *temp = xstrdup(cmdstr), *temp2 = temp; - - while (go) { - int len = strcspn(temp2, "\n"); - if (!temp2[len]) go = 0; - else temp2[len] = 0; - add_cmd(temp2); - temp2 += len+1; - } - free(temp); + char *sv, *eol; + + cmdstr = sv = xstrdup(cmdstr); + do { + eol = strchr(cmdstr, '\n'); + next: + if (eol) { + /* Count preceding slashes */ + int slashes = 0; + char *sl = eol; + + while (sl != cmdstr && *--sl == '\\') + slashes++; + /* Odd number of preceding slashes - newline is escaped */ + if (slashes & 1) { + strcpy(eol-1, eol); + eol = strchr(eol, '\n'); + goto next; + } + *eol = '\0'; + } + add_cmd(cmdstr); + cmdstr = eol + 1; + } while (eol); + free(sv); } static void add_cmds_link(llist_t *opt_e) diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 9576b6c4b..a054de6d7 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -146,6 +146,10 @@ rm outputw testing "sed trailing NUL" \ "sed 's/i/z/' input -" \ "a\0b\0\nc" "a\0b\0" "c" +testing "sed escaped newline in command" \ + "sed 's/a/z\\ +z/' input" \ + "z\nz" "a" "" # Test end-of-file matching behavior |