89 lines
2.3 KiB
Bash
Executable File
89 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
usage () {
|
|
echo "usage: grep.sh [-nlivx] [-e] pattern file [...]"
|
|
exit 1
|
|
}
|
|
|
|
# no arguments
|
|
LN= # be sure variables are reset
|
|
FN=
|
|
RV=
|
|
FL=
|
|
MULTI=
|
|
|
|
# parse args:
|
|
while getopts ":nlivxe" arg; do
|
|
case $arg in
|
|
n) LN=t ;; # will print line number
|
|
l) FN=t ;; # only file names
|
|
i) shopt -s nocasematch ;; # case insensitive
|
|
v) RV=t ;; # reverse search
|
|
x) FL=t ;; # full line search
|
|
e) break ;; # not in exercise: end args
|
|
*) usage ;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
# need at least pattern and 1 file.
|
|
# TODO: consider stdin if no file
|
|
[[ $# < 2 ]] && usage
|
|
[[ $# > 2 ]] && MULTI=t
|
|
|
|
# full line match
|
|
if [[ $FL = t ]]; then
|
|
pattern="^$1\$"
|
|
else
|
|
pattern=".*$1.*"
|
|
fi
|
|
|
|
shift
|
|
|
|
# will prevent leading/trailing whitespaces to be trimmed
|
|
IFS=""
|
|
|
|
while [[ $# > 0 ]]; do
|
|
file="$1"
|
|
if [[ ! -r "$file" ]]; then
|
|
echo "$file: no such file, or not readable."
|
|
exit 1
|
|
fi
|
|
|
|
lnum=0 # line number
|
|
|
|
match=n
|
|
while read -r line ; do # will consider '\' as normal char
|
|
(( lnum ++ ))
|
|
|
|
if [[ $line =~ $pattern ]] ; then # line match
|
|
match=y
|
|
|
|
# print only filename, go to next file
|
|
[[ $FN = t ]] && echo "$file" && break
|
|
|
|
# not reverse matching only
|
|
if [[ $RV != t ]]; then
|
|
# multiple files: print filename
|
|
[[ $MULTI == t ]] && echo -n "$file:"
|
|
[[ $LN = t ]] && echo -n "$lnum:"
|
|
echo "$line"
|
|
fi
|
|
else
|
|
# reverse match
|
|
if [[ $RV == t ]]; then
|
|
# print only filename, go to next file
|
|
[[ $FN = t ]] && echo "$file" && break
|
|
|
|
# multiple files: print filename
|
|
[[ $MULTI == t ]] && echo -n "$file:"
|
|
[[ $LN = t ]] && echo -n "$lnum:"
|
|
echo "$line"
|
|
fi
|
|
fi
|
|
done < "$1"
|
|
|
|
shift # next file
|
|
done
|
|
exit 0
|