If statement syntax eror - shell

I am trying to figure out how to check to see if the first input will end with .txt. It seems like the standard if statement syntax does not apply to my code based upon the way I am getting the input. Does anyone know the proper syntax for the else if statement in my first if statement in my code?
#!/bin/sh
printf "%b %b\n" "$*"
if [ "$1" = "-help" ]
then
echo "Cool Beans"
elif [ "$1" = "*.txt" ]
then
echo "text recd"
else
echo "first input not valid"
fi
if [ "$2" = "-help" ]
then
echo "help options"
else
echo "second input not valid"
fi

In order for pattern matching to work, can use Bash double-bracketed conditionals (while removing the quotes, which disable the matching) :
elif [[ "$1" = *.txt ]]
You can also use regular expression matching :
elif [[ "$1" =~ [.]txt$ ]]
Note that you must escape the period (or put it in brackets like I did) to prevent its special meaning of "any character" to be disabled, as well as anchor the regex to the end with $ so that you are sure you are matching the extension, not a sub-string inside the file name.
If you want something that is not bash-specific, you can try :
elif [ "${1##*.}" = txt ]
The "${1##*.}" expansion removes the longest string that starts from the beginning of the variable named 1 (could be any variable) and ends with a period, leaving the extension only.

You can also use a case statement for POSIX-compatible pattern matching:
printf "%b %b\n" "$*"
case $1 in
-help) echo "Cool Beans" ;;
*.txt) echo "text recd" ;;
*) echo "first input not valid"
esac
case $2 in
-help) echo "help options" ;;
*) echo "second input not valid" ;;
esac

Related

if condition inside function is not working as desired when function called with command line arguments inside find statement

#!/bin/bash
# Code to generate script usage
if [[ "$#" -ne 1 ]] && [[ "$#" -ne 2 ]]; then
flag=1;
elif ! [[ "$1" == "abcd" || "$1" == "dcba" ]]; then
echo "Invalid"
flag=1;
fi
while [ $# -gt 1 ]
do
case $2 in
'streams')
;;
*)
echo "unrecognised optional arg $2"; flag=1;
;;
esac
shift
done
if [ "$flag" == "1" ]; then
echo "Usage:"
exit
fi
function main {
arg1=$1
streams=$2
if [ "${streams}" == "streams" ]; then
echo entering here
else
echo entering there
fi
}
parent_dir=`pwd`
find $parent_dir -name "*" -type d | while read d; do
cd $denter code here
main $1 $2
done
Why the code does not enter "entering here" when script run with arguments "abcd" and "streams" ?
I feel that function having two arguments is causing the problem, code was working fine with one argument
Several things you might want to fix in your code, before attempts are made to find the specific problem. It is possible that it will disappear after modifying your script accordingly. If the problem is still alive, I'll edit my answer with a solution. If you decide to apply the following changes, please update your code in the question.
Consistent usage of either [[ or [. [[ is a Bash keyword similar to (but more powerful than) the [ command.
See
Bash FAQ 31
Tests And Conditionals
Unless you're writing for POSIX sh, I recommend [[.
Use (( for arithmetic expressions. ((...)) is an arithmetic command, which returns an exit status of 0 if the expression is nonzero, or 1 if the expression is zero. Also used as a synonym for let, if assignments are needed. See Arithmetic Expression.
Use the variable PWD instead of pwd. PWD is a builtin variable in all POSIX shells that contains the current working directory. pwd(1) is a POSIX utility that prints the name of the current working directory to stdout. Unless you're writing for some non-POSIX system, there is no reason to waste time executing pwd(1) rather than just using PWD.
The function keyword is not portable. I suggest you to avoid using it and simply write function_name() { your code here; } # Usage
$parent_dir is not double-quoted. "Double quote" every literal that contains spaces/metacharacters and every expansion: "$var", "$(command "$var")", "${array[#]}", "a & b". See
Quotes
Arguments
ShellCheck your code before uploading.
Replace the while condition logic with an if condition, so that shift is no longer required. Shift was the devil I was facing I found.
#!/bin/bash
# Code to generate script usage
if [[ "$#" -ne 1 ]] && [[ "$#" -ne 2 ]]; then
flag=1;
elif ! [[ "$1" == "abcd" || "$1" == "dcba" ]]; then
echo "Invalid"
flag=1;
fi
#while [[ $# -gt 1 ]]
#do
# case $2 in
# 'streams')
# ;;
# *)
# echo "unrecognised optional arg $2"; flag=1;
# ;;
# esac
# shift
#done
if [[ $2 == "streams" ]]; then
:
elif [[ (-z $2) ]]; then
:
else
echo "unrecognised optional arg $2"; flag=1;
fi
if [[ "$flag" == "1" ]]; then
echo "Usage:"
exit
fi
function main {
streams=$2
if [[ "${streams}" == "streams" ]]; then
echo entering here
else
echo entering there
fi
}
parent_dir=`pwd`
find $parent_dir -name "*" -type d | while read d; do
cd $d
main $1 $2
done

if statement checking regex expression not working

I have start learning shell programming today, what I am trying out is to do a simple option menu with 3 choices and if the user key in 1,2 or 3, it will be a valid input. anything besides 1,2,3 will be a invalid input.I have tried it out but it's not working as in nothing happened with my codes below.
Please advice thanks.
#!/bin/bash
while :
do
clear
#display menu
echo "1) choice 1"
echo "2) choice 2"
echo "3) choice 3"
read -p "Enter choice: " choice
regex = "[1-3]"
if [[ $choice -ne $regex ]]; then
echo "Invalid input"
else
case $choice in
1) echo "this is choice one"
2) echo "this is choice two"
3) echo "this is choice three"
esac
fi
done
You're not comparing it as a regex. Say:
if [[ ! $choice =~ $regex ]]; then
Moreover, you shouldn't put spaces are = during assignment. Say:
regex="[1-3]"
From the manual:
An additional binary operator, ‘=~’, is available, with the same
precedence as ‘==’ and ‘!=’. When it is used, the string to the right
of the operator is considered an extended regular expression and
matched accordingly
Don't clear or you won't see anything.
Errors
Remove the blanks around =:
regex="[1-3]"
Your cases must end with ;;:
1) echo "this is choice one";;
2) echo "this is choice two";;
3) echo "this is choice three";;
Suggestions
Introduce an exit case:
'x') exit 0;;
The test [[ ]] is not needed if you use a default case as the last case:
*) echo "invalid input";;

Check input consists only of numeric characters in shell script

I need to check that the input consists only of numeric characters. I have the code below, but it didn't work properly.
if [[ $1 =~ [0-9] ]]; then
echo "Invalid input"
fi
It should give true only for 678686 not for yy66666.
How about this:-
re='^[0-9]+$'
if ! [[ $Number =~ $re ]] ; then
echo "error: Invalid input" >&2; exit 1
fi
or
case $Number in
''|*[!0-9]*) echo nonnumeric;;
*) echo numeric;;
esac
Try using start/end anchors with your pattern. If you don't, the match succeeds with a part of a test string. Don't forget that you have to use a pattern matching the complete test string if you follow this suggestion.
if [[ $1 =~ ^[0-9]+$ ]]; then
echo "Invalid input"
fi
Check out this SO post for more details.

Shell script check if variable contains spaces

I am new to shell scripting. I have a variable containing path to specific file. I want to check if this variable has any spaces in it.
I tried with
if [[ ${VAR} = "${VAR% *}" ]] ; then
echo "contains spaces"
else
echo "doesnot contain spaces"
fi
But it doesn't work. Any help will be really appreciable.
or
case ${VAR} in
*\ * ) echo "VAR=$VAR has at least one space char" ;;
* ) echo "VAR=$VAR has no space chars" ;;
esac
IHTH
Good solution but you need to reverse the conditions. ${VAR% *} strips up to the last space, so if it is equal to ${VAR} then there weren't any spaces.
You should escape the first ${VAR} in "" as well in case it is empty.
if [[ "${VAR}" == "${VAR% *}" ]] ; then
echo "doesn't contains spaces"
else
echo "contains spaces"
fi
Another solution:
echo $VAR | grep ".*\s.*" && echo "Space exists" || echo "No space exists"

How do i compare 2 strings in shell?

I want the user to input something at the command line either -l or -e.
so e.g. $./report.sh -e
I want an if statement to split up whatever decision they make so i have tried...
if [$1=="-e"]; echo "-e"; else; echo "-l"; fi
obviously doesn't work though
Thanks
I use:
if [[ "$1" == "-e" ]]; then
echo "-e"
else
echo "-l";
fi
However, for parsing arguments, getopts might make your life easier:
while getopts "el" OPTION
do
case $OPTION in
e)
echo "-e"
;;
l)
echo "-l"
;;
esac
done
If you want it all on one line (usually it makes it hard to read):
if [ "$1" = "-e" ]; then echo "-e"; else echo "-l"; fi
You need spaces between the square brackets and what goes inside them. Also, just use a single =. You also need a then.
if [ $1 = "-e" ]
then
echo "-e"
else
echo "-l"
fi
The problem specific to -e however is that it has a special meaning in echo, so you are unlikely to get anything back. If you try echo -e you'll see nothing print out, while echo -d and echo -f do what you would expect. Put a space next to it, or enclose it in brackets, or have some other way of making it not exactly -e when sending to echo.
If you just want to print which parameter the user has submitted, you can simply use echo "$1". If you want to fall back to a default value if the user hasn't submitted anything, you can use echo "${1:--l} (:- is the Bash syntax for default values). However, if you want really powerful and flexible argument handling, you could look into getopt:
params=$(getopt --options f:v --longoptions foo:,verbose --name "my_script.sh" -- "$#")
if [ $? -ne 0 ]
then
echo "getopt failed"
exit 1
fi
eval set -- "$params"
while true
do
case $1 in
-f|--foo)
foobar="$2"
shift 2
;;
-v|--verbose)
verbose='--verbose'
shift
;;
--)
while [ -n "$3" ]
do
targets[${#targets[*]}]="$2"
shift
done
source_dir=$(readlink -fn -- "$2")
shift 2
break
;;
*)
echo "Unhandled parameter $1"
exit 1
;;
esac
done
if [ $# -ne 0 ]
then
error "Extraneous parameters." "$help_info" $EX_USAGE
fi

Resources