[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