How to check length of an argument in bash script - bash

how can I check the length of an argument in bash script?
Let's say that the length of an argument should not exceed 1.
args=("$#")
if [ ${args[0] -gt 1]; then
echo "Length of arg. 1 must be 1"
fi
This however doesn't work properly, since it will check if args[0] > 1 and not len(args[0] > 1):
./sth.sh 2 1 1
"Length of arg. 1 must be 1"
LENGTH is 1, but it still echoes.
I also tried this:
args=("$#")
if [ ${#args[0] -gt 1]; then
echo "Length of arg. 1 must be 1"
fi
However, it doesn't echo anything.

You can use this:
if [ "$#" -ne 1 ]; then
echo "Illegal number of parameters"
fi
Or
if test "$#" -ne 1; then
echo "Illegal number of parameters"
fi
Later check the length of each argument like this:
for var in "$#"
do
check=${#var}
if [ $check -ne 1 ]; then echo "error" ; exit
fi
done

Related

How to fix count that doesn't work in while loop

I have been trying to resolve an issue where my loop's count should decrease, however nothing is working. I need to create a while loop that will read over a given amount of times. For instance, if I enter in "files.txt -a 3" in the terminal, I need my loop to repeat "Enter in a string: " 3 times. With my code below, I am only able to get it to loop once. I am not to sure where to put the counter and I can say that I have put it everywhere. Inside the if statement, in inside of the for loop, and inside the while loop but none seem to work. The number that the user will put is held in the $count variable.
#!/bin/bash
if ["$1" = "-a" ]
then
read in user String and save into file
fi
while [ "$count" > 0 ]
do
for i in $count
do
if [ "-a" ]
then
read -p "Enter in a string: " userSTR
echo userSTR >> files.txt
count=$(($count - 1))
fi
done
done
For conditional expression you need to use [[ expression ]], e.g. this will loop four times:
count=4
while [[ $count > 0 ]] ; do
echo "$count"
count=$(( $count - 1 ))
done
To fetch the count from the command-line argument, you could replace the assignment count=4 above with the following, parsing the command-line arguments:
if [ $# -lt 2 ] ; then
echo "Usage: $0 -a [count]"
exit 1
fi
if [ "$1" = "-a" ] ; then
shift
count=$1
fi

Shell script to output the largest

How to write a script which will receive a list of parameters and output the number that is the largest. If no parameters are supplied, output an error message.
I wrote the following code to check if no parameters are supplied, output an error message.
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "No arugments supplied"
else
echo "$# Parameter"
But I dont know how to continue...
Keep a current max. Loop over the input, updating max if necessary. At the end you'll have the global maximum.
Untested:
#!/usr/bin/bash
if [ $# -eq 0 ]; then
echo "Usage: $0 NUMBERS" >&2
exit 1;
fi
max="$1"
shift
while [ $# -gt 0 ]; do
if [ "$1" -gt "$max" ]; then
max="$1"
fi
shift
done
echo "$max"
Use sort -n (numeric) and -r (reverse) and then just pick the first line of the output -- like
#!/bin/bash
if [ "$#" -eq "0" ]
then
echo "No arugments supplied"
else
echo "$# Parameter"
for i in $*; do echo ${i}; done | sort -nr | head -1
fi
Now the only problem you are facing is when the the input (the arguments) are not numbers -- but you didn't say anything about what should happen then.
Here's a pseudocode you could implement:
save the first param in a variable called max
loop over the params
if the param is greater than max, update max
print max
Here's an example loop that prints all parameters:
for num; do
echo $num
done
And here's an example of comparing values:
if (( num > max )); then
echo $num is greater than $max
fi
This should be more than enough help to complete your homework.
Well since others have already gave you the actual solution, here's mine too:
#!/bin/bash
if (( $# == 0 )); then
echo "No arugments supplied"
exit 1
fi
max=$1
for num; do
if (( num > max )); then
max=$num
fi
done
echo $max

Counting down in a loop to zero by the number being given

I am trying to write a while loop to determine the number is being given to count down to 0. Also, if there's no argument given, must display "no parameters given.
Now I have it counting down but the last number is not being 0 and as it is counting down it starts with the number 1. I mush use a while loop.
My NEW SCRIPT.
if [ $# -eq "0" ] ;then
echo "No paramters given"
else
echo $#
fi
COUNT=$1
while [ $COUNT -gt 0 ] ;do
echo $COUNT
let COUNT=COUNT-1
done
echo Finished!
This is what outputs for me.
sh countdown.sh 5
1
5
4
3
2
1
Finished!
I need it to reach to 0
#Slizzered has already spotted your problem in a comment:
You need operator -ge (greater than or equal) rather than -gt (greater than) in order to count down to 0.
As for why 1 is printed first: that's simply due to the echo $# statement before the while loop.
If you're using bash, you could also consider simplifying your code with this idiomatic reformulation:
#!/usr/bin/env bash
# Count is passed as the 1st argument.
# Abort with error message, if not given.
count=${1?No parameters given}
# Count down to 0 using a C-style arithmetic expression inside `((...))`.
# Note: Increment the count first so as to simplify the `while` loop.
(( ++count ))
while (( --count >= 0 )); do
echo $count
done
echo 'Finished!'
${1?No parameters given} is an instance of shell parameter expansion
bash shell arithmetic is documented here.
You should also validate the variable before using it in an arithmetic context. Otherwise, a user can construct an argument that will cause the script to run in an infinite loop or hit the recursion limit and segfault.
Also, don't use uppercase variable names since you risk overriding special shell variables and environment variables. And don't use [ in bash; prefer the superior [[ and (( constructs.
#!/usr/bin/env bash
shopt -s extglob # enables extended globs
if (( $# != 1 )); then
printf >&2 'Missing argument\n'
exit 1
elif [[ $1 != +([0-9]) ]]; then
printf >&2 'Not an acceptable number\n'
exit 2
fi
for (( i = $1; i >= 0; i-- )); do
printf '%d\n' "$i"
done
# or if you insist on using while
#i=$1
#while (( i >= 0 )); do
# printf '%d\n' "$((i--))"
#done
Your code is far from being able to run. So, I don't know where to start to explain. Let's take this small script:
#!/bin/sh
die() {
echo $1 >&2
exit 1;
}
test -z "$1" && die "no parameters given"
for i in $(seq $1 -1 0); do
echo "$i"
done
The main part is the routine seq which does what you need: counting from start value to end value (with increment in between). The start value is $1, the parameter to our script, the increment is -1.
The test line tests whether there is a parameter on the command line - if not, the script ends via the subroutine die.
Hth.
There are a number of ways to do this, but the general approach is to loop from the number given to an ending number decrementing the loop count with each iteration. A C-style for loop works as well as anything. You will adjust the sleep value to get the timing you like. You should also validate the required number and type of input your script takes. One such approach would be:
#!/bin/bash
[ -n "$1" ] || {
printf " error: insufficient input. usage: %s number (for countdown)\n" "${0//*\//}"
exit 1
}
[ "$1" -eq "$1" >/dev/null 2>&1 ] || {
printf " error: invalid input. number '%s' is not an integer\n" "$1"
exit 1
}
declare -i cnt=$(($1))
printf "\nLaunch will occur in:\n\n"
for ((i = cnt; i > 0; i--)); do
printf " %2s\n" "$i"
sleep .5
done
printf "\nFinished -- blastoff!\n\n"
exit 0
Output
$ bash ./scr/tmp/stack/countdown.sh 10
Launch will occur in:
10
9
8
7
6
5
4
3
2
1
Finished -- blastoff!
Your Approach
Your approach is fine, but you need to use the value of COUNT $COUNT in your expression. You also should declare -i COUNT=$1 to tell the shell to treat it as an integer:
#!/bin/bash
if [ $# -eq "0" ] ;then
echo "No paramters given"
else
echo -e "\nNumber of arguments: $#\n\n"
fi
declare -i COUNT=$1
while [ $COUNT -gt 0 ] ;do
echo $COUNT
let COUNT=$COUNT-1
done
echo -e "\nFinished!\n"

How to use the exit status from a function within my script

I have a script and within it I call a function. How can I use the exit status from the function to print a message, without incorporating the message inside the function?
I am supposed to write a script which has:
Your script should contain a function increasingNos that uses three parameters. All three parameters should be integers. The function is a "success" (with exit status 0) if there are exactly three parameters and they are numbers in increasing order. The function should have an exit status of 1 if there are three parameters but they are not in increasing order. The function should should have an exit status of 2 if there are fewer or more than 3 parameters.
and...
you should print an appropriate message to the standard output after calling increasingNos with parameters 17 5 23 to say whether or not there were three parameters and whether or not they were numbers in increasing order. Use an if conditional and the exit status on your function call to do this. This if conditional may not be in the function increasingNos.
This is what I have come up; whenever I run the script, it exits when the function call hits an exit status. How can I execute the rest of the script?
increasingNos(){
if [ $# -ne 3 ];then
exit 2
fi
if [ $1 -ge $2 ] || [ $2 -ge $3 ];then
exit 1
else
exit 0
fi
}
increasingNos 17 5 23
if [ $? -eq 2 ];then
echo "You did not supply exactly 3 integer parameters!"
fi
if [ $? -eq 1 ];then
echo "Your parameters were not input in increasing order!"
fi
if [ $? -eq 0 ];then
echo "Congrats, you supplied 3 integers in increasing order!"
fi
Use return instead of exit and save the value of $? in a variable, because it will change after the first test.
This works:
increasingNos(){
if [ $# -ne 3 ];then
return 2
fi
if [ $1 -ge $2 ] || [ $2 -ge $3 ];then
return 1
else
return 0
fi
}
increasingNos 17 5 23
stat=$?
if [ $stat -eq 2 ];then
echo "You did not supply exactly 3 integer parameters!"
fi
if [ $stat -eq 1 ];then
echo "Your parameters were not input in increasing order!"
fi
if [ $stat -eq 0 ];then
echo "Congrats, you supplied 3 integers in increasing order!"
fi
You need to use return rather than exit in your functions.

How to count and check passed arguments?

How can I translate the following Ruby code to Bash?
if ARGV.length == 0
abort "\nError: The project name is required. Aborting...\n\n"
elsif ARGV.length > 2
abort "\nError: The program takes two arguments maximum. Aborting...\n\n"
end
#!/bin/bash
USAGE="$0: <project name> [subproject attribute]"
if [ $# -lt 1 ]; then echo -e "Error: The project name is required.\n$USAGE" >&2; exit 1; fi
if [ $# -gt 2 ]; then echo -e "Error: Two arguments maximum.\n$USAGE" >&2; exit 1; fi
The following should be what you need:
#!/bin/bash
if [ $# -eq 0 ]; then
echo -e "\nError: The project name is required. Aborting...\n\n"
exit 1
elif [ $# -gt 2 ]; then
echo -e "\nError: The program takes two arguments maximum. Aborting...\n\n"
exit 1
fi
The TLDP bash guide is very good if you are looking to learn bash, see TDLP Bash guide.
Maybe:
#!/bin/bash
function functionName {
if [ $# = 0 ]
then echo "\nError: The project name is required. Aborting...\n\n"; exit 1
fi
if [ $# \> 2 ]
then echo "\nError: The program takes two arguments maximum. Aborting...\n\n"; exit 1
fi
}
functionName a

Resources