[PATCH 1/1] sed: /regex/,+N ranges

Denys Vlasenko vda.linux at googlemail.com
Fri Apr 17 15:14:53 UTC 2015


Pushed the fix to git.

Please try.

On Thu, Apr 16, 2015 at 6:07 PM, Denys Vlasenko
<vda.linux at googlemail.com> wrote:
> It fails a case where we have more than one file:
>
> testing "sed -i finishes ranges correctly" \
>         "cat - >input2; sed /^4/,+2{d} -i input input2; echo \$?; cat
> input input2; rm input2" \
>         "0\n""1\n2\n3\n7\n8\n""1\n2\n7\n8\n" \
>         "1\n2\n3\n4\n5\n6\n7\n8\n" \
>         "1\n2\n4\n5\n6\n7\n8\n"
>
> I'm working on a code which will handle this too.
>
> On Wed, Apr 15, 2015 at 1:35 AM, Bernhard Reutner-Fischer
> <rep.dot.nop at gmail.com> wrote:
>> 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