Created
December 20, 2021 14:49
-
-
Save hexaflexahexagon/3d3b41049b70f330ee493f7027187c6e to your computer and use it in GitHub Desktop.
# Emulate the functionality of grep through regular expressions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Emulate the functionality of grep through regular expressions | |
# ./script -a = echo a a | |
# ./script a = echo a at end of file | |
# ./script -g = echo idk | |
# ./script what = echo $@ | |
opts="n l i v x" | |
let FLAG_LINENUMS | |
let FLAG_FILENAME | |
let FLAG_CASEINSR | |
let FLAG_DOINVERT | |
let FLAG_FULLLINE | |
while getopts "$opts" flag; do | |
case $flag in | |
n) # -n: print line numbers in output | |
FLAG_LINENUMS=1 | |
;; | |
l) # -l: print the names of files with one+ matching lines | |
FLAG_FILENAME=1 | |
;; | |
i) # -i: case-insensitive matching | |
FLAG_CASEINSR=1 | |
;; | |
v) # -v: invert the matching | |
FLAG_DOINVERT=1 | |
;; | |
x) # -x: only match full lines | |
FLAG_FULLLINE=1 | |
;; | |
?) echo Example parameters: | |
echo -n: display line numbers | |
echo -l: print file names with any matching lines | |
echo -i: case-insensitive | |
echo -v: invert matching rules | |
echo -x: only match full lines | |
exit -1 | |
;; | |
esac | |
done | |
shift $((OPTIND - 1)) | |
regex=$1 | |
input=$(echo "$@" | cut -d' ' -f2) | |
allInput=$(echo "$@" | cut -d' ' -f3-) | |
totalInput=$(echo $allInput | wc -w) | |
totalInput=$((totalInput + 1)) | |
# Validation | |
if [ -z "$regex" ]; then | |
echo Error: Please supply both a string to search for and one or more file names to search through | |
exit -1 | |
fi | |
if [ -z "$input" ]; then | |
echo Error: Please supply a file name | |
exit -1 | |
fi | |
if ! [ -a "$input" ]; then | |
echo Error: File \""$input"\" not found | |
exit -1 | |
fi | |
# Full-line flag | |
if ! [ -z $FLAG_FULLLINE ]; then | |
regex=^${regex}$ | |
fi | |
while ! [[ $input == "" ]]; do | |
# Start reading a file | |
i=1 | |
foundMatch=false | |
while read -r line; do | |
# lineCount=$(wc -l "$input" | cut -d' ' -f 1) | |
lineCompare=$line | |
# Case-insensitive flag | |
if ! [ -z $FLAG_CASEINSR ]; then | |
regex=$( echo $regex | tr '[:upper:]' '[:lower:]' ) | |
lineCompare=$( echo $line | tr '[:upper:]' '[:lower:]' ) | |
fi | |
if ! [ -z $FLAG_FILENAME ]; then | |
# Inverted matching pattern flag | |
if ! [ -z $FLAG_DOINVERT ]; then | |
if ! [[ $lineCompare =~ ($regex) ]]; then | |
foundMatch=true | |
fi | |
else | |
if [[ $lineCompare =~ ($regex) ]]; then | |
foundMatch=true | |
fi | |
fi | |
else | |
# Formatting if we're using multiple files or not | |
if [[ $totalInput -gt 1 ]]; then | |
inputDisplay="$input:" | |
else | |
inputDisplay="" | |
fi | |
# Inverted matching pattern flag | |
if ! [ -z $FLAG_DOINVERT ]; then | |
if ! [[ $lineCompare =~ ($regex) ]]; then | |
# Line numbering in output flag | |
if ! [ -z $FLAG_LINENUMS ]; then | |
echo $input:$i: $line | |
else | |
echo $input: $line | |
fi | |
fi | |
else | |
if [[ $lineCompare =~ ($regex) ]]; then | |
# Line numbering in output flag | |
if ! [ -z $FLAG_LINENUMS ]; then | |
echo $inputDisplay$line | |
else | |
echo $inputDisplay$line | |
fi | |
fi | |
fi | |
i=$(($i + 1)) | |
fi | |
done < $input | |
if [[ $foundMatch == true ]]; then | |
echo $input | |
fi | |
# If more files were input, start to process them | |
if [[ $(echo "$allInput" | wc -w) -gt 1 ]]; then | |
input=$(echo "$allInput" | cut -d' ' -f1) | |
allInput=$(echo "$allInput" | cut -d' ' -f2-) | |
elif [[ $(echo "$allInput" | wc -w) -eq 1 ]]; then | |
input=$allInput | |
allInput="" | |
else | |
input="" | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment