1 /* vi: set sw=4 ts=4: */
3 * Mini sed implementation for busybox
6 * Copyright (C) 1999,2000 by Lineo, inc.
7 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
9 * Modifications for addresses and append command have been
10 * written by Marco Pantaleoni <panta@prosa.it>, <panta@elasticworld.org>
12 * Copyright (C) 1999 Marco Pantaleoni.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 static const char sed_usage[] =
41 "sed [-n] -e script [file...]\n"
42 #ifndef BB_FEATURE_TRIVIAL_HELP
43 "\nAllowed sed scripts come in the following form:\n"
44 "\t'ADDR [!] COMMAND'\n\n"
45 "\twhere address ADDR can be:\n"
46 "\t NUMBER Match specified line number\n"
47 "\t $ Match last line\n"
48 "\t /REGEXP/ Match specified regexp\n"
49 "\t (! inverts the meaning of the match)\n\n"
50 "\tand COMMAND can be:\n"
51 "\t s/regexp/replacement/[igp]\n"
52 "\t which attempt to match regexp against the pattern space\n"
53 "\t and if successful replaces the matched portion with replacement.\n\n"
55 "\t which appends TEXT after the pattern space\n"
57 "-e\tadd the script to the commands to be executed\n"
58 "-n\tsuppress automatic printing of pattern space\n\n"
60 "This version of sed matches full regular expressions.\n";
62 "This version of sed matches strings (not full regular expressions).\n"
67 /* Flags & variables */
69 typedef enum { f_none, f_replace, f_append } sed_function;
73 static int addr_line = NO_LINE;
74 static char *addr_pattern = NULL;
75 static int negated = 0;
77 #define SKIPSPACES(p) do { while (isspace(*(p))) (p)++; } while (0)
81 static inline int at_last(FILE * fp)
90 if ((ch = fgetc(fp)) == EOF)
97 static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
98 int ignoreCase, int printFlag, int quietFlag)
100 int foundOne = FALSE;
101 char haystack[BUFSIZE];
104 while (fgets(haystack, BUFSIZE - 1, fp)) {
107 doit = !find_match(haystack, addr_pattern, FALSE);
108 } else if (addr_line == NO_LINE)
110 else if (addr_line == LAST_LINE) {
114 if (line == addr_line)
121 replace_match(haystack, needle, newNeedle, ignoreCase);
123 if (foundOne == TRUE && printFlag == TRUE) {
124 fprintf(stdout, haystack);
128 if (quietFlag == FALSE) {
129 fprintf(stdout, haystack);
136 static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
138 char buffer[BUFSIZE];
141 while (fgets(buffer, BUFSIZE - 1, fp)) {
144 doit = !find_match(buffer, addr_pattern, FALSE);
145 } else if (addr_line == NO_LINE)
147 else if (addr_line == LAST_LINE) {
151 if (line == addr_line)
156 if (quietFlag == FALSE) {
157 fprintf(stdout, buffer);
160 fputs(appendline, stdout);
168 extern int sed_main(int argc, char **argv)
171 char *needle = NULL, *newNeedle = NULL;
174 int ignoreCase = FALSE;
175 int printFlag = FALSE;
176 int quietFlag = FALSE;
178 char *line_s = NULL, saved;
179 char *appendline = NULL;
181 sed_function sed_f = f_none;
196 while (*++cp && stopNow == FALSE) {
202 if (*(cp + 1) == 0 && --argc < 0) {
208 /* Read address if present */
211 addr_line = LAST_LINE;
214 if (isdigit(*cp)) { /* LINE ADDRESS */
222 addr_line = atoi(line_s);
225 } else if (*cp == '/') { /* PATTERN ADDRESS */
226 pos = addr_pattern = cp + 1;
227 pos = strchr(pos, '/');
245 case 's': /* REPLACE */
246 if (strlen(cp) <= 3 || *(cp + 1) != '/')
250 pos = needle = cp + 2;
253 pos = strchr(pos, '/');
257 if (*(pos - 1) == '\\') {
266 pos = strchr(pos, '/');
270 if (*(pos - 1) == '\\') {
294 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
297 case 'a': /* APPEND */
302 /* fprintf(stderr, "append '%s'\n", appendline); */
320 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
324 do_sed_append(stdin, appendline, quietFlag);
331 fp = fopen(name, "r");
341 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
345 do_sed_append(fp, appendline, quietFlag);