# egrep.awk --- simulate egrep in awk # # Arnold Robbins, arnold@skeeve.com, Public Domain # May 1993 # Revised September 2020 # Options: # -c count of lines # -e argument is pattern # -i ignore case # -l print filenames only # -n add line number to output # -q quiet - use exit value # -s silent - don't print errors # -v invert test, success if no match # -x the entire line must match # # Requires getopt library function # Uses IGNORECASE, BEGINFILE and ENDFILE # Invoke using gawk -f egrep.awk -- options ... BEGIN { while ((c = getopt(ARGC, ARGV, "ce:ilnqsvx")) != -1) { if (c == "c") count_only++ else if (c == "e") pattern = Optarg else if (c == "i") IGNORECASE = 1 else if (c == "l") filenames_only++ else if (c == "n") line_numbers++ else if (c == "q") no_print++ else if (c == "s") no_errors++ else if (c == "v") invert++ else if (c == "x") full_line++ else usage() } if (pattern == "") pattern = ARGV[Optind++] if (pattern == "") usage() for (i = 1; i < Optind; i++) ARGV[i] = "" if (Optind >= ARGC) { ARGV[1] = "-" ARGC = 2 } else if (ARGC - Optind > 1) do_filenames++ } BEGINFILE { fcount = 0 if (ERRNO && no_errors) nextfile } ENDFILE { if (! no_print && count_only) { if (do_filenames) print file ":" fcount else print fcount } total += fcount } { matches = match($0, pattern) if (matches && full_line && (RSTART != 1 || RLENGTH != length())) matches = 0 if (invert) matches = ! matches fcount += matches # 1 or 0 if (! matches) next if (! count_only) { if (no_print) nextfile if (filenames_only) { print FILENAME nextfile } if (do_filenames) if (line_numbers) print FILENAME ":" FNR ":" $0 else print FILENAME ":" $0 else print } } END { exit (total == 0) } function usage() { print("Usage:\tegrep [-cilnqsvx] [-e pat] [files ...]") > "/dev/stderr" print("\tegrep [-cilnqsvx] pat [files ...]") > "/dev/stderr" exit 1 } # getopt.awk --- Do C library getopt(3) function in awk # Also supports long options. # # Arnold Robbins, arnold@skeeve.com, Public Domain # # Initial version: March, 1991 # Revised: May, 1993 # Long options added by Greg Minshall, January 2020 # External variables: # Optind -- index in ARGV of first nonoption argument # Optarg -- string value of argument to current option # Opterr -- if nonzero, print our own diagnostic # Optopt -- current option letter # Returns: # -1 at end of options # "?" for unrecognized option # a string representing the current option # Private Data: # _opti -- index in multiflag option, e.g., -abc function getopt(argc, argv, options, longopts, thisopt, i, j) { if (length(options) == 0 && length(longopts) == 0) return -1 # no options given if (argv[Optind] == "--") { # all done Optind++ _opti = 0 return -1 } else if (argv[Optind] !~ /^-[^:[:space:]]/) { _opti = 0 return -1 } if (argv[Optind] !~ /^--/) { # if this is a short option if (_opti == 0) _opti = 2 thisopt = substr(argv[Optind], _opti, 1) Optopt = thisopt i = index(options, thisopt) if (i == 0) { if (Opterr) printf("%c -- invalid option\n", thisopt) > "/dev/stderr" if (_opti >= length(argv[Optind])) { Optind++ _opti = 0 } else _opti++ return "?" } if (substr(options, i + 1, 1) == ":") { # get option argument if (length(substr(argv[Optind], _opti + 1)) > 0) Optarg = substr(argv[Optind], _opti + 1) else Optarg = argv[++Optind] _opti = 0 } else Optarg = "" if (_opti == 0 || _opti >= length(argv[Optind])) { Optind++ _opti = 0 } else _opti++ return thisopt } else { j = index(argv[Optind], "=") if (j > 0) thisopt = substr(argv[Optind], 3, j - 3) else thisopt = substr(argv[Optind], 3) Optopt = thisopt i = match(longopts, "(^|,)" thisopt "($|[,:])") if (i == 0) { if (Opterr) printf("%s -- invalid option\n", thisopt) > "/dev/stderr" Optind++ return "?" } if (substr(longopts, i+1+length(thisopt), 1) == ":") { if (j > 0) Optarg = substr(argv[Optind], j + 1) else Optarg = argv[++Optind] } else Optarg = "" Optind++ return thisopt } } BEGIN { Opterr = 1 # default is to diagnose Optind = 1 # skip ARGV[0] # test program if (_getopt_test) { _myshortopts = "ab:cd" _mylongopts = "longa,longb:,otherc,otherd" while ((_go_c = getopt(ARGC, ARGV, _myshortopts, _mylongopts)) != -1) printf("c = <%s>, Optarg = <%s>\n", _go_c, Optarg) printf("non-option arguments:\n") for (; Optind < ARGC; Optind++) printf("\tARGV[%d] = <%s>\n", Optind, ARGV[Optind]) } }