[PATCH 1/1] sed: /regex/,+N ranges
Bernhard Reutner-Fischer
rep.dot.nop at gmail.com
Tue Apr 14 23:35:54 UTC 2015
function old new delta
add_cmd 1207 1359 +152
process_files 2502 2530 +28
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 180/0) Total: 180 bytes
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com>
---
editors/sed.c | 36 +++++++++++++++++++++++++++++++-----
testsuite/sed.tests | 12 ++++++++++++
2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/editors/sed.c b/editors/sed.c
index 2c64ad5..7d7e17c 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -640,10 +640,25 @@ static void add_cmd(const char *cmdstr)
int idx;
cmdstr++;
- idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
+ if (*cmdstr == '+') {
+ /* http://sed.sourceforge.net/sedfaq3.html#s3.3
+ * Under GNU sed 3.02+, ssed, and sed15+, <address2>
+ * may also be a notation of the form +num,
+ * indicating the next num lines after <address1> is
+ * matched. */
+ /* Set both end_line and end_match to distinguish this case */
+ idx = strtol(cmdstr, (char**)&cmdstr, 10);
+ if (cmdstr == NULL)
+ idx = 0;
+ sed_cmd->end_line = idx;
+ sed_cmd->end_match = xzalloc(sizeof(regex_t));
+ xregcomp(sed_cmd->end_match, ".*", REG_EXTENDED);
+ } else {
+ idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match);
+ cmdstr += idx;
+ }
if (!idx)
bb_error_msg_and_die("no address after comma");
- cmdstr += idx;
}
/* skip whitespace before the command */
@@ -1089,10 +1104,21 @@ static void process_files(void)
/* Is this line the end of the current match? */
if (matched) {
- /* once matched, "n,xxx" range is dead, disabling it */
- if (sed_cmd->beg_line > 0) {
- sed_cmd->beg_line = -2;
+ if (sed_cmd->end_line && sed_cmd->end_match) {
+ /* address2 is +N, i.e. N lines from beg_line */
+ sed_cmd->end_line--;
+ sed_cmd->beg_line++;
+ } else {
+ /* once matched, "n,xxx" range is dead, disabling it */
+ if (sed_cmd->beg_line > 0) {
+ sed_cmd->beg_line = -2;
+ }
}
+ dbg("end1:%d", sed_cmd->end_line ? sed_cmd->end_line == -1
+ ? !next_line : (sed_cmd->end_line <= linenum)
+ : !sed_cmd->end_match);
+ dbg("end2:%d", sed_cmd->end_match && old_matched
+ && !regexec(sed_cmd->end_match,pattern_space, 0, NULL, 0));
sed_cmd->in_match = !(
/* has the ending line come, or is this a single address command? */
(sed_cmd->end_line
diff --git a/testsuite/sed.tests b/testsuite/sed.tests
index 19f2915..399230f 100755
--- a/testsuite/sed.tests
+++ b/testsuite/sed.tests
@@ -333,6 +333,18 @@ testing "sed s///NUM test" \
"sed -e 's/a/b/2; s/a/c/g'" \
"cb\n" "" "aa\n"
+testing "sed /regex/,N/{} addresses work" \
+ "sed /^2/,2{d}" \
+ "1\n3\n4\n5\n" \
+ "" \
+ "1\n2\n3\n4\n5\n"
+
+testing "sed /regex/,+N/{} addresses work" \
+ "sed /^2/,+2{d}" \
+ "1\n5\n" \
+ "" \
+ "1\n2\n3\n4\n5\n"
+
# testing "description" "commands" "result" "infile" "stdin"
exit $FAILCOUNT
--
2.1.4
More information about the busybox
mailing list