aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtests/sed.test2
-rw-r--r--toys/posix/sed.c16
2 files changed, 11 insertions, 7 deletions
diff --git a/tests/sed.test b/tests/sed.test
index beb11d5c..c3928e58 100755
--- a/tests/sed.test
+++ b/tests/sed.test
@@ -185,6 +185,8 @@ testing '\n with empty capture' \
testing '\n too high' \
'sed -E "s/(.*)/\2/p" 2>/dev/null || echo OK' "OK\n" "" "foo"
+toyonly testing 's///x' 'sed "s/(hello )?(world)/\2/x"' "world" "" "hello world"
+
# Performance test
X=x; Y=20; while [ $Y -gt 0 ]; do X=$X$X; Y=$(($Y-1)); done
testing 'megabyte s/x/y/g (20 sec timeout)' \
diff --git a/toys/posix/sed.c b/toys/posix/sed.c
index 8fbef0cb..9bd05034 100644
--- a/toys/posix/sed.c
+++ b/toys/posix/sed.c
@@ -147,7 +147,7 @@ struct sedcmd {
int rmatch[2]; // offset of regex struct for prefix matches (/abc/,/def/p)
int arg1, arg2, w; // offset of two arguments per command, plus s//w filename
unsigned not, hit;
- unsigned sflags; // s///flag bits: i=1, g=2, p=4
+ unsigned sflags; // s///flag bits: i=1, g=2, p=4, x=8
char c; // action
};
@@ -441,7 +441,7 @@ static void sed_line(char **pline, long plen)
} else zmatch = 0;
// If we're replacing only a specific match, skip if this isn't it
- off = command->sflags>>3;
+ off = command->sflags>>4;
if (off && off != ++count) {
memcpy(l2+l2used, rline, match[0].rm_eo);
l2used += match[0].rm_eo;
@@ -793,6 +793,7 @@ static void parse_pattern(char **pline, long len)
if (!TT.nextlen--) break;
} else if (c == 's') {
char *end, delim = 0;
+ int flags;
// s/pattern/replacement/flags
@@ -845,19 +846,20 @@ resume_s:
if (isspace(*line) && *line != '\n') continue;
- if (0 <= (l = stridx("igp", *line))) command->sflags |= 1<<l;
+ if (0 <= (l = stridx("igpx", *line))) command->sflags |= 1<<l;
else if (*line == 'I') command->sflags |= 1<<0;
- else if (!(command->sflags>>3) && 0<(l = strtol(line, &line, 10))) {
- command->sflags |= l << 3;
+ else if (!(command->sflags>>4) && 0<(l = strtol(line, &line, 10))) {
+ command->sflags |= l << 4;
line--;
} else break;
}
+ flags = (FLAG(r) || (command->sflags&8)) ? REG_EXTENDED : 0;
+ if (command->sflags&1) flags |= REG_ICASE;
// We deferred actually parsing the regex until we had the s///i flag
// allocating the space was done by extend_string() above
if (!*TT.remember) command->arg1 = 0;
- else xregcomp((void *)(command->arg1 + (char *)command), TT.remember,
- (REG_EXTENDED*!!FLAG(r))|((command->sflags&1)*REG_ICASE));
+ else xregcomp((void *)(command->arg1+(char *)command),TT.remember,flags);
free(TT.remember);
TT.remember = 0;
if (*line == 'w') {