I want to test if the first argument is one of: "ABC" or "DEF" or "GHI".
And if it's not - print usage and exit.
if [[ "$1" =~ ^(ABC|DEF|GHI)$ ]]; then
echo "usage"
exit
fi
This case runs in sh and bash:
case "$1" in
'ABC' | 'DEF' | 'GHI') ;;
*) echo "usage"
exit;;
esac
You could just use a normal if statement with string comparison:
if [ "$1" != "ABC" -a "$1" != "DEF" -a "$1" != "GHI" ]; then
echo "Usage: $0 ABC|DEF|GHI"
exit 0
fi
Or:
if [ "$1" = "ABC" -o "$1" = "DEF" -o "$1" = "GHI" ]; then
# Do something.
else
echo "Usage: $0 ABC|DEF|GHI"
exit 0
fi
Related
#!/bin/bash
helpFunc()
{
echo "Usage:
$0 --arg1
$0 --arg2 filename add/delete/replace "hi how are you"
$0 --help
"
}
function fileread() {
pwd
echo "Fileread Function"
if [ -f $filename ]
then
echo "file exists"
filename=$1
cat $1
case "$1" in
add|ADD)
read $1
if [$2 == 'add' ]
then
echo $3 >> $1
echo "add opeartion completed"
fi
shift
;;
delete|DELETE)
read $1
echo "echo delet string from file"
if [$2 == 'delete' ]
then
sed '/$3/d' $1
echo "add opeartion completed"
fi
shift
;;
replace|REPLACE)
read $1
if [ $4 == 'replace' ]
then
sed "s/$5/$6/g" "$1" > temp.txt
else
echo "Error: Cannot read $1"
fi
shift
;;
esac
shift
# return 0
else
echo "file not exist"
#return 1
fi
}
while [ $# ]
do
case "$1" in
--a)
if [ -z "$2" ]
then
echo "No argument supplied"
echo "hello" && echo " current process id : $$ "
else
echo -e "no need of sending arguments for --a"
helpFunc a;
exit 1
shift
fi
;;
--b)
if [ $( echo -e $2 | grep -c -E "^-" ) -eq 0 ]
then
fileName=$2
if [ -f "$fileName" ]
then
echo -e "The file is valid"
echo "Displaying $2 file..."
[ -z $fileName ] && { echo "File name missing"; exit 1; } || cat $fileName
case "$filename" in
add|ADD)
echo "adding"
fileread $3 $4
shift
;;
delete|DELETE)
echo "echo deleting"
fileread
shift
;;
replace|REPLACE)
echo "replacing"
fileread
shift
;;
esac
else
echo -e "please enter the valid file name or location"
helpFunc b;
exit 1
shift
fi
fi
esac
shift
done
exit 0
function file read should ignore the case inputs like ADD/add , delete/Delete etc.. and perform operations if i give the cmd line arguments and values and it should validate case sensitivity, file existence and path of the file
./script.sh -a -b /etc/opt/test.txt ADD "hi how are you" delete "i am fine" REPLACE "hi " "hey"
I am using if statement with multiple condition in bash.
How can I reduce the following line syntax. So that it looks good from design point of you.
if [ "$1" != "-l" ] && [ "$1" != "-a" ] && [ "$1" != "-h" ] && [ "$1" != "" ] && [ "$1" = "-d" ] || [ "$1" = "-mv" ] || [ "$1" = "-dv" ] || [ "$1" = "-mr" ] || [ "$1" = "-dr" ];
Thanks
Use pattern matching.
if [[ $1 && $1 != -[lah] && $1 == -#(d|mv|dv|mr|dr) ]]; then
#(...) is an example of an extended pattern, which should be recognized by default inside [[ ... ]] in recent versions of bash. If you version is not so recent, add shopt -s extglob to the beginning of your script.
In fact, you can drop the $1 && $1 != -[lah] because its truth would be implied by the truth of $1 == -#(...).
if [[ $1 == -#(d|mv|dv|mr|dr) ]]; then
You could also just use a POSIX-compliant case statement:
case $1 of
-d|-mv|-dv|-mr|-dr) echo good option ;;
*) echo bad option ;;
esac
You can create 2 arrays for matching and non matching values and check if element $1 matches any element in the array or not like below.
nonmatch_array=( "-l" "-a" "-h" "" )
match_array=( "-d" "-mv" "-dv" "-mr" "-dr" )
if [ `echo ${match_array[#]} | grep "$1"` ] || ! [ `echo ${nonmatch_array[#]} | grep "$1"` ] ; then
echo "is in array"
else
echo "is not in array"
fi
Hope it should work for you.
First try to limit the length of the code on 1 line.
if [ [ "$1" != "-l" ]
&& [ "$1" != "-a" ]
&& [ "$1" != "-h" ]
&& [ -n "$1" ]
&& ( [ "$1" = "-d" ]
|| [ "$1" = "-mv" ]
|| [ "$1" = "-dv" ]
|| [ "$1" = "-mr" ]
|| [ "$1" = "-dr" ] ) ];
I added braces, to make clear what you mean with the or's.
Now you can combine all matches with a regular expression:
if [[ ! ("$a" =~ ^-(l|a|h|d|)$)
&& "$a" =~ ^-(mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
but reconsider what you are testing. The test will only be true when it matches -mv/-dv/-mr/-dr, so you do not need to test for the options lah.
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
You can use a variable for extracting the options:
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
Everytime the code is becoming hard to read (and also for long code or repeating statements), you should consider using a function.
The next function is short, but hard to read:
options="d|mv|dv|mr|dr"
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
checkoption1 "$a" &&
echo "Yes $a matches"
I would choose for a slightly more verbose function. I will include your original tests for lah for showing the possibilities.
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
checkoption2 "$a" &&
echo "Yes $a matches"
You should make some testruns before accepting your code.
I have made some tests with a small loop (now all answers together)
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
for a in -mv mv -mvx -ms -mr -dr; do
if [[ ! ("$a" =~ ^-(l|a|h|)$)
&& "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
checkoption1 "$a" &&
echo "Yes $a matches"
checkoption2 "$a" &&
echo "Yes $a matches 2"
done
I received an assignment in school where I'm suppose to generate output in a random color if specified. My program doesn't generate the color that I would like it to when the RANDOM option is selected.
My input to the program is:
echoc RANDOM|colour string
And my code looks like:
declare -A colours=(
[black]="0;30" [red]="0;31" [green]="0;32" [yellow]="0;33" [blue]="0;34" [magenta]="0;35" [cyan]="0;36" [white]="0;37"
[BLACK]="1;30" [RED]="1;31" [GREEN]="1;32" [YELLOW]="1;33" [BLUE]="1;34" [MAGENTA]="1;35" [CYAN]="1;36" [WHITE]="1;37")
if [ $# -lt 2 ]; then
echo "Usage: echoc COLOUR|RANDOM STRING"
exit 1
fi
regex='^red$|^green$|^yellow$|^blue$|^magenta$|^cyan$|^white|^black$'
shopt -s nocasematch
if [[ $1 =~ $regex ]]; then
printf '\033[%sm' ${colours[$1]}
shift
printf '%s\033[0m\n' "$*"
exit 0
elif [[ $1 == "RANDOM" ]]; then
printf '\033[%sm' ${colours[$((RANDOM%8+1))]}
shift
printf '%s\033[0m\n' "$*"
exit 3
else
echo COLOUR must be one of 'red|green|yellow|blue|magenta|cyan|white|RANDOM'
exit 2
fi
declare -A colours=(
[1]="0;30" [2]="0;31" [3]="0;32" [4]="0;33" [5]="0;34" [6]="0;35" [7]="0;36" [8]="0;37"
[black]="0;30" [red]="0;31" [green]="0;32" [yellow]="0;33" [blue]="0;34" [magenta]="0;35" [cyan]="0;36" [white]="0;37"
[BLACK]="1;30" [RED]="1;31" [GREEN]="1;32" [YELLOW]="1;33" [BLUE]="1;34" [MAGENTA]="1;35" [CYAN]="1;36" [WHITE]="1;37")
if [ $# -lt 2 ]; then
echo "Usage: echoc COLOUR|RANDOM STRING"
exit 1
fi
regex='^red$|^green$|^yellow$|^blue$|^magenta$|^cyan$|^white|^black$'
shopt -s nocasematch
if [[ $1 =~ $regex ]]; then
printf '\033[%sm' ${colours[$1]}
shift
printf '%s\033[0m\n' "$*"
exit 0
elif [[ $1 == "RANDOM" ]]; then
derp=$(($RANDOM%8+1))
printf '\033[%sm' ${colours["$derp"]}
shift
printf '%s\033[0m\n' "$*"
exit 3
else
echo COLOUR must be one of 'red|green|yellow|blue|magenta|cyan|white|RANDOM'
exit 2
fi
Why I have a integer expression expected error with this:
at=`echo $1 | grep -q "#"`
if [ $at -ne 0 ]; then
echo "blabla"
else
echo "bloblo"
fi
$at is set, and the test working fine outside the script
When testing the result of grep -q, you want to test $? not the output of grep, which will be empty
at=$(echo "$1" | grep -q "#")
if [ $? -ne 0 ]; then ...
or simply
if echo "$1" | grep -q "#"; then ...
or, more bash-ly
if grep -q "#" <<< "$1"; then ...
or, without calling grep:
if [[ "$1" == *#* ]]; then ...
or
case "$1" in
*#*) echo "match" ;;
*) echo "no match" ;;
esac
-ne is for comparing integers. Use != to compare strings.
DISPLAY_HEADER=1
if [ "$1" != "test" -o "$1" != "test2" ]
then
if [ $DISPLAY_HEADER == 1 ]; then
DISPLAY_HEADER=0
echo "sdasa "
echo $1
fi
fi
its display sdasa and -o is not working ?
what is wrong ?
you can use case/esac
case "$1" in
test|test2)
# do something
*)
# set display data
;;
esac