001: /*
002: * gnu/regexp/util/Grep.java
003: * Copyright (C) 1998 Wes Biggs
004: *
005: * This program is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU General Public License as published
007: * by the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
018: */
019:
020: package gnu.regexp.util;
021:
022: import gnu.getopt.Getopt;
023: import gnu.getopt.LongOpt;
024: import gnu.regexp.RE;
025: import gnu.regexp.REException;
026: import gnu.regexp.REMatch;
027: import gnu.regexp.RESyntax;
028: import java.io.BufferedReader;
029: import java.io.FileInputStream;
030: import java.io.FileNotFoundException;
031: import java.io.InputStream;
032: import java.io.InputStreamReader;
033: import java.io.IOException;
034: import java.io.PrintStream;
035:
036: /**
037: * Grep is a pure-Java clone of the GNU grep utility. As such, it is much
038: * slower and not as full-featured, but it has the advantage of being
039: * available on any system with a Java virtual machine.
040: *
041: * @author <A HREF="mailto:wes@cacas.org">Wes Biggs</A>
042: * @version 1.01
043: * @use gnu.getopt
044: */
045: public class Grep {
046: private static final int BYTE_OFFSET = 0;
047: private static final int COUNT = 1;
048: private static final int LINE_NUMBER = 2;
049: private static final int QUIET = 3;
050: private static final int SILENT = 4;
051: private static final int NO_FILENAME = 5;
052: private static final int REVERT_MATCH = 6;
053: private static final int FILES_WITH_MATCHES = 7;
054: private static final int LINE_REGEXP = 8;
055: private static final int FILES_WITHOUT_MATCH = 9;
056:
057: private static final String PROGNAME = "gnu.regexp.util.Grep";
058: private static final String PROGVERSION = "1.01";
059:
060: private Grep() {
061: }
062:
063: /**
064: * Invokes the grep() function below with the command line arguments
065: * and using the RESyntax.RE_SYNTAX_GREP syntax, which attempts to
066: * emulate the traditional UNIX grep syntax.
067: */
068: public static void main(String[] argv) {
069: System.exit(grep(argv, RESyntax.RE_SYNTAX_GREP, System.out));
070: }
071:
072: /**
073: * Runs Grep with the specified arguments. For a list of
074: * supported options, specify "--help".
075: *
076: * This is the meat of the grep routine, but unlike main(), you can
077: * specify your own syntax and PrintStream to use for output.
078: */
079: public static int grep(String[] argv, RESyntax syntax,
080: PrintStream out) {
081: // use gnu.getopt to read arguments
082: int cflags = 0;
083:
084: boolean[] options = new boolean[10];
085:
086: LongOpt[] longOptions = {
087: new LongOpt("byte-offset", LongOpt.NO_ARGUMENT, null,
088: 'b'),
089: new LongOpt("count", LongOpt.NO_ARGUMENT, null, 'c'),
090: new LongOpt("no-filename", LongOpt.NO_ARGUMENT, null,
091: 'h'),
092: new LongOpt("ignore-case", LongOpt.NO_ARGUMENT, null,
093: 'i'),
094: new LongOpt("files-with-matches", LongOpt.NO_ARGUMENT,
095: null, 'l'),
096: new LongOpt("help", LongOpt.NO_ARGUMENT, null, '!'),
097: new LongOpt("line-number", LongOpt.NO_ARGUMENT, null,
098: 'n'),
099: new LongOpt("quiet", LongOpt.NO_ARGUMENT, null, 'q'),
100: new LongOpt("silent", LongOpt.NO_ARGUMENT, null, 'q'),
101: new LongOpt("no-messages", LongOpt.NO_ARGUMENT, null,
102: 's'),
103: new LongOpt("revert-match", LongOpt.NO_ARGUMENT, null,
104: 'v'),
105: new LongOpt("line-regexp", LongOpt.NO_ARGUMENT, null,
106: 'x'),
107: new LongOpt("extended-regexp", LongOpt.NO_ARGUMENT,
108: null, 'E'),
109: new LongOpt("fixed-strings", LongOpt.NO_ARGUMENT, null,
110: 'F'), // TODO
111: new LongOpt("basic-regexp", LongOpt.NO_ARGUMENT, null,
112: 'G'),
113: new LongOpt("files-without-match", LongOpt.NO_ARGUMENT,
114: null, 'L'),
115: new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'V') };
116:
117: Getopt g = new Getopt(PROGNAME, argv, "bchilnqsvxyEFGLV",
118: longOptions);
119: int c;
120: String arg;
121: while ((c = g.getopt()) != -1) {
122: switch (c) {
123: case 'b':
124: options[BYTE_OFFSET] = true;
125: break;
126: case 'c':
127: options[COUNT] = true;
128: break;
129: case 'h':
130: options[NO_FILENAME] = true;
131: break;
132: case 'i':
133: case 'y':
134: cflags |= RE.REG_ICASE;
135: break;
136: case 'l':
137: options[FILES_WITH_MATCHES] = true;
138: break;
139: case 'n':
140: options[LINE_NUMBER] = true;
141: break;
142: case 'q':
143: options[QUIET] = true;
144: break;
145: case 's':
146: options[SILENT] = true;
147: break;
148: case 'v':
149: options[REVERT_MATCH] = true;
150: break;
151: case 'x':
152: options[LINE_REGEXP] = true;
153: break;
154: case 'E': // TODO: check compatibility with grep
155: syntax = RESyntax.RE_SYNTAX_EGREP;
156: break;
157: case 'F': // TODO: fixed strings
158: break;
159: case 'G':
160: syntax = RESyntax.RE_SYNTAX_GREP;
161: break;
162: case 'L':
163: options[FILES_WITHOUT_MATCH] = true;
164: break;
165: case 'V':
166: System.err.println(PROGNAME + ' ' + PROGVERSION);
167: return 0;
168: case '!': // help
169: BufferedReader br = new BufferedReader(
170: new InputStreamReader((Grep.class)
171: .getResourceAsStream("GrepUsage.txt")));
172: String line;
173: try {
174: while ((line = br.readLine()) != null)
175: out.println(line);
176: } catch (IOException ie) {
177: }
178: return 0;
179: }
180: }
181:
182: InputStream is = null;
183: RE pattern = null;
184: int optind = g.getOptind();
185: if (optind >= argv.length) {
186: System.err.println("Usage: java " + PROGNAME
187: + " [OPTION]... PATTERN [FILE]...");
188: System.err.println("Try `java " + PROGNAME
189: + " --help' for more information.");
190: return 2;
191: }
192: try {
193: pattern = new RE(argv[g.getOptind()], cflags, syntax);
194: } catch (REException e) {
195: System.err.println("Error in expression: " + e);
196: return 2;
197: }
198: int retval = 1;
199: if (argv.length >= g.getOptind() + 2) {
200: for (int i = g.getOptind() + 1; i < argv.length; i++) {
201: if (argv[i].equals("-")) {
202: if (processStream(pattern, System.in, options,
203: (argv.length == g.getOptind() + 2)
204: || options[NO_FILENAME] ? null
205: : "(standard input)", out)) {
206: retval = 0;
207: }
208: } else {
209: try {
210: is = new FileInputStream(argv[i]);
211: if (processStream(pattern, is, options,
212: (argv.length == g.getOptind() + 2)
213: || options[NO_FILENAME] ? null
214: : argv[i], out))
215: retval = 0;
216: } catch (FileNotFoundException e) {
217: if (!options[SILENT])
218: System.err.println(PROGNAME + ": " + e);
219: }
220: }
221: }
222: } else {
223: if (processStream(pattern, System.in, options, null, out))
224: retval = 1;
225: }
226: return retval;
227: }
228:
229: private static boolean processStream(RE pattern, InputStream is,
230: boolean[] options, String filename, PrintStream out) {
231: int newlineLen = System.getProperty("line.separator").length();
232: BufferedReader br = new BufferedReader(
233: new InputStreamReader(is));
234: int count = 0;
235: long atByte = 0;
236: int atLine = 1;
237: String line;
238: REMatch match;
239:
240: try {
241: while ((line = br.readLine()) != null) {
242: match = pattern.getMatch(line);
243: if (((options[LINE_REGEXP] && pattern.isMatch(line)) || (!options[LINE_REGEXP] && (match != null)))
244: ^ options[REVERT_MATCH]) {
245: count++;
246: if (!options[COUNT]) {
247: if (options[QUIET]) {
248: return true;
249: }
250: if (options[FILES_WITH_MATCHES]) {
251: if (filename != null)
252: out.println(filename);
253: return true;
254: }
255: if (options[FILES_WITHOUT_MATCH]) {
256: return false;
257: }
258: if (filename != null) {
259: out.print(filename);
260: out.print(':');
261: }
262: if (options[LINE_NUMBER]) {
263: out.print(atLine);
264: out.print(':');
265: }
266: if (options[BYTE_OFFSET]) {
267: out.print(atByte + match.getStartIndex());
268: out.print(':');
269: }
270: out.println(line);
271: }
272: } // a match
273: atByte += line.length() + newlineLen; // could be troublesome...
274: atLine++;
275: } // a valid line
276: br.close();
277:
278: if (options[COUNT]) {
279: if (filename != null)
280: out.println(filename + ':');
281: out.println(count);
282: }
283: if (options[FILES_WITHOUT_MATCH] && count == 0) {
284: if (filename != null)
285: out.println(filename);
286: }
287: } catch (IOException e) {
288: System.err.println(PROGNAME + ": " + e);
289: }
290: return ((count > 0) ^ options[REVERT_MATCH]);
291: }
292: }
|