mirror of
git://git.suckless.org/sbase
synced 2024-12-21 22:50:16 +00:00
xargs: add replace string flag (-I)
This commit is contained in:
parent
f14887c765
commit
8d97acc135
1
Makefile
1
Makefile
@ -78,6 +78,7 @@ LIBUTILSRC =\
|
||||
libutil/strlcat.c\
|
||||
libutil/strlcpy.c\
|
||||
libutil/strsep.c\
|
||||
libutil/strnsubst.c\
|
||||
libutil/strtonum.c\
|
||||
libutil/unescape.c\
|
||||
libutil/writeall.c
|
||||
|
62
libutil/strnsubst.c
Normal file
62
libutil/strnsubst.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2002 J. Mallett. All rights reserved.
|
||||
* You may do whatever you want with this file as long as
|
||||
* the above copyright and this notice remain intact, along
|
||||
* with the following statement:
|
||||
* For the man who taught me vi, and who got too old, too young.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../util.h"
|
||||
|
||||
/*
|
||||
* Replaces str with a string consisting of str with match replaced with
|
||||
* replstr as many times as can be done before the constructed string is
|
||||
* maxsize bytes large. It does not free the string pointed to by str, it
|
||||
* is up to the calling program to be sure that the original contents of
|
||||
* str as well as the new contents are handled in an appropriate manner.
|
||||
* If replstr is NULL, then that internally is changed to a nil-string, so
|
||||
* that we can still pretend to do somewhat meaningful substitution.
|
||||
* No value is returned.
|
||||
*/
|
||||
void
|
||||
strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
|
||||
{
|
||||
char *s1, *s2, *this;
|
||||
size_t matchlen, s2len;
|
||||
int n;
|
||||
|
||||
if ((s1 = *str) == NULL)
|
||||
return;
|
||||
s2 = emalloc(maxsize);
|
||||
|
||||
if (replstr == NULL)
|
||||
replstr = "";
|
||||
|
||||
if (match == NULL || *match == '\0' || strlen(s1) >= maxsize) {
|
||||
strlcpy(s2, s1, maxsize);
|
||||
goto done;
|
||||
}
|
||||
|
||||
*s2 = '\0';
|
||||
s2len = 0;
|
||||
matchlen = strlen(match);
|
||||
for (;;) {
|
||||
if ((this = strstr(s1, match)) == NULL)
|
||||
break;
|
||||
n = snprintf(s2 + s2len, maxsize - s2len, "%.*s%s",
|
||||
(int)(this - s1), s1, replstr);
|
||||
if (n == -1 || n + s2len + strlen(this + matchlen) >= maxsize)
|
||||
break; /* out of room */
|
||||
s2len += n;
|
||||
s1 = this + matchlen;
|
||||
}
|
||||
strlcpy(s2 + s2len, s1, maxsize - s2len);
|
||||
done:
|
||||
free(*str);
|
||||
*str = s2;
|
||||
return;
|
||||
}
|
2
util.h
2
util.h
@ -63,6 +63,8 @@ size_t estrlcpy(char *, const char *, size_t);
|
||||
#define strsep xstrsep
|
||||
char *strsep(char **, const char *);
|
||||
|
||||
void strnsubst(char **, const char *, const char *, size_t);
|
||||
|
||||
/* regex */
|
||||
int enregcomp(int, regex_t *, const char *, int);
|
||||
int eregcomp(regex_t *, const char *, int);
|
||||
|
8
xargs.1
8
xargs.1
@ -1,4 +1,4 @@
|
||||
.Dd 2015-10-08
|
||||
.Dd 2023-07-30
|
||||
.Dt XARGS 1
|
||||
.Os sbase
|
||||
.Sh NAME
|
||||
@ -8,6 +8,7 @@
|
||||
.Nm
|
||||
.Op Fl rtx
|
||||
.Op Fl E Ar eofstr
|
||||
.Op Fl I Ar replstr
|
||||
.Op Fl n Ar num
|
||||
.Op Fl s Ar num
|
||||
.Op Ar cmd Op Ar arg ...
|
||||
@ -44,6 +45,11 @@ Normally the command is executed at least once even if there are no arguments.
|
||||
Use
|
||||
.Ar eofstr
|
||||
as a logical EOF marker.
|
||||
.It Fl I Ar replstr
|
||||
Use
|
||||
.Ar replstr
|
||||
as the placeholder for the argument.
|
||||
Sets the arguments count to 1 per command line.
|
||||
.It Fl s Ar num
|
||||
Use at most
|
||||
.Ar num
|
||||
|
16
xargs.c
16
xargs.c
@ -195,10 +195,11 @@ usage(void)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret = 0, leftover = 0, i;
|
||||
int ret = 0, leftover = 0, ri = 0, i;
|
||||
size_t argsz, argmaxsz;
|
||||
size_t arglen, a;
|
||||
char *arg = "";
|
||||
char *replstr;
|
||||
|
||||
if ((argmaxsz = sysconf(_SC_ARG_MAX)) == (size_t)-1)
|
||||
argmaxsz = _POSIX_ARG_MAX;
|
||||
@ -225,6 +226,11 @@ main(int argc, char *argv[])
|
||||
case 'E':
|
||||
eofstr = EARGF(usage());
|
||||
break;
|
||||
case 'I':
|
||||
nflag = 1;
|
||||
maxargs = 1;
|
||||
replstr = EARGF(usage());
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
} ARGEND
|
||||
@ -235,6 +241,8 @@ main(int argc, char *argv[])
|
||||
for (; i < argc; i++) {
|
||||
cmd[i] = estrdup(argv[i]);
|
||||
argsz += strlen(cmd[i]) + 1;
|
||||
if (!strcmp(cmd[i], replstr))
|
||||
ri = i;
|
||||
}
|
||||
} else {
|
||||
cmd[i] = estrdup("/bin/echo");
|
||||
@ -252,7 +260,11 @@ main(int argc, char *argv[])
|
||||
leftover = 1;
|
||||
break;
|
||||
}
|
||||
cmd[i] = estrdup(arg);
|
||||
if (ri > 0)
|
||||
strnsubst(&cmd[ri], replstr, arg, 255);
|
||||
else
|
||||
cmd[i] = estrdup(arg);
|
||||
|
||||
argsz += arglen + 1;
|
||||
i++;
|
||||
a++;
|
||||
|
Loading…
Reference in New Issue
Block a user