I'm trying to grep multiple arguments in shell. I put orders like ./script arg1 arg2.. argN And I want them to act egrep -i "arg1" mydata | egrep -i "arg2" | ... egrep -i "argN" | awk -f display.awk in order to match patterns in AND format. What's wrong in my process?
Is it even right to code like egrep -i "arg1" mydata | egrep -i "arg2" | ... egrep -i "argN" | awk -f display.awk to get multiple patterns in AND format??
if [ $# -eq 0 ]
then
echo "Usage:phone searchfor [...searchfor]"
echo "(You didn't tell me what you want to search for.)"
exit 0
else
for arg in $*
do
if [ $arg -eq $1 ]
then
egrep -i "arg" mydata |
else
egrep -i "arg" |
fi
done
awk -f display.awk
fi
If my data has 'happy sunny bunny', 'sleepy bunny', and 'happy sunny'
I want them to perform if I tried ./script happy sunny bunny then only 'happy sunny bunny' comes out.
and if i tried ./script bunny then 'happy sunny bunny' 'sleepy bunny' both coming out.
The immediate fix is to move the pipe character to after the done
.
Also, you should loop over "$@"
to preserve the quoting of your arguments, and generally quote your variables.
if [ $# -eq 0 ]
then
# print diagnostics to stderr
echo "Usage: phone searchfor [...searchfor]" >&2
echo "(You didn't tell me what you want to search for.)" >&2
exit 0
fi
for arg in "$@"
do
# Add missing dash before eq
if [ "$arg " -eq "$1" ]
then
# Surely you want "$arg" here, not the static string "arg"?
grep -E -i "$arg" mydata
else
grep -E -i "$arg"
fi
done |
awk -f display.awk
The overall logic still seems flawed; you will be grepping standard input for the first argument if there are more than two arguments. Perhaps you want to add an option to allow the user to specify an input file name, with -
to specify standard input? And then all the regular arguments will be search strings, like the usage message suggests.
If indeed the intent is to loop over all the arguments to produce a logical AND, try this:
also () {
local what
what=$1
shift
if [ $# -gt 0 ]; then
grep -E -i "$what" | also "$@"
else
grep -E -i "$what"
fi
}
also "$@" <mydata | awk -f display.awk
... though a better implementation might be to build a simple Awk or sed
script from the arguments:
script='1'
for arg in "$@"; do
script="$script && tolower(\$0) ~ tolower(\"$arg\")"
done
awk "$script" | awk -f display.awk
This breaks down if the search phrases could contain regex specials, though (which of course is true for the grep -E
version as well; but then you could easily switch to grep -F
).
Merging the two Awk scripts into one should probably not be hard either, though without seeing display.awk
, this is speculative.