initial commit
This commit is contained in:
88
bash/grep/grep.sh
Executable file
88
bash/grep/grep.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/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
|
Reference in New Issue
Block a user