the task is to write a shell script
inputs are a string and a number
for example,
xxx.sh "Hello World" 3
the input will be
***************
* Hello World *
* Hello World *
* Hello World *
***************
and here is what have I got so far:
function mantra() {
echo "string is $1"
echo "number is $2"
echo $string
echo $PATH
for num in string_length; do
echo "*"
done
}
How do I count the number of characters in the string?
Am I doing right? I am not exactly sure how to pass command-line arguments into my function.Blockquote
The number of characters in your input string is ${#1}
See this page for a short explanation.
#!/bin/sh
function mantra() {
string=$1
num=$2
strlen=${#string}
let strlen=$strlen+2
echo -n "*"
for (( times = 0; times < $strlen; times++ )); do echo -n "*" ; done
echo "*";
}
mantra $1 $2
for (( times = 0; times < $num; times++ )); do
echo "* $string *"
done
mantra $1 $2
Related
I am trying to create below pattern design in Shell script, i have written below codes for the same but i am not getting expected results. can someone help on this?
Desired output-->
*
**
***
****
*****
#! /bin/sh
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
if [ $j > 6-$i ]
then
echo -n "* "
elif [ $j == 6-$i ]
then
echo -n "* "
else
echo -n " "
fi
done
echo
done
Current output-->
*****
*****
*****
*****
*****
You will need to use another loop to print the pre-pending spaces.
for ((i=1;i<=5;i++)); # Loop to create 5 lines of text
do
for((k=1;k<=(5-i);k++)); # Loop to padd prepending spaces
do
printf "%s" " ";
done;
for ((j=1;j<=i;j++)); # Loop to create asterix
do
printf "%s" "*";
done;
printf "\n"; # Print the carriage return
done
to make the minimum number of changes to your code to get it working; you need to do number comparison, and number addition in order to get your check statements to work:
for ((i=1; i<=5; i++)) ; do
for ((j=1; j<=5; j++)) ; do
if [ $j -ge $((6-$i)) ] ; then
echo -n "* "
else
echo -n " "
fi
done
echo
done
new output:
*
* *
* * *
* * * *
* * * * *
It doesn't need so much arithmetic, you can use printf to add the padding:
n=5
line=''
char='*'
for ((i=1; i<=n; i++)); do
line+=$char
printf "%*s\n" $n "$line"
done
If you want the triangle leaning the other way:
printf "%-*s\n" $n "$line"
I have to write a script in bash where I have to provide 10 numbers to the table. Then script have to write the content out and arithmetic mean of even numbers. I did like 90% of the script, but I can't find out how to extract information about quantity of even numbers that is needed for arithmetic mean.
Here is my code:
echo "Provide data:"
i=0
for (( i = 0 ; i < 10; i++ ))
do
echo "Provide $[$i+1] number:"
read x
if [ "$x" = "" ]
then
break
else
table[$i]=$x
fi
done
echo "Provided data: ${table[*]}"
result=0
for (( i = 0 ; i < 10; i++))
do
res=$[${table[i]}%2]
if [ $res -eq 0 ]
then
echo "Number ${table[i]} is even"
result=$[$result+${table[$i]}]
fi
done
echo "SUM:$[$result]"
ignoring data input adding only odd inputs can look like :
$ cat c.sh
#!/bin/bash
declare -A xDarray
sum=0
xDarray[0 1]=1
xDarray[0 2]=3
xDarray[1 0]=2
xDarray[2 0]=4
for var in ${xDarray[#]}
do
if [ $(( $var & 1 )) == 0 ] ; then
echo $var is even
i+=1
tab[$i]=$var
sum=$(( $sum + $var))
fi
done
var=$(echo ${tab[#]} | sed 's/ / + /g' )
echo $var = $sum
result in
$ ./c.sh
2 is even
4 is even
2 + 4 = 6
$
whatever the number of data is used it would work
I let you work around your data input
Here are some suggested modifications for your script, syntax is simple.
#!/bin/bash
arr=()
for (( i=1;i<=10;i++ )); do
number=''
while [[ ! $number =~ ^[0-9]+$ ]]; do
printf "Please enter number $i:\n"
read number
done
arr+=($number)
done
printf "\nProvided numbers:"
printf " %d" "${arr[#]}"
printf "\nEven numbers:"
s=0
n=0
for x in "${arr[#]}"; do
if ! (( x % 2 )); then
printf " %d" "$x"
s=$(( s + x ))
(( n++ ))
fi
done
m=$(( s / n ))
printf "\nMean of the %d even numbers: %d / %d = %d\n" "$n" "$s" "$n" "$m"
Use an array arr to hold the input numbers, declare with arr=(), append numbers with arr+=($x), we refer only ${arr[#]} for all the items and we avoid any other complex array references, indices etc.
Every input number is tested against regular expression ^[0-9]+$ which means one or more digits (and only digits) with the =~ operator, and if this is not true, we prompt again for the same i-th input number.
Also we prefer printf for printing.
The last loop is the standard array loop, where we use again the arithmetic expansion syntax to find the even numbers, to add them to the sum and get the mean of them (result is an integer).
If you want to print a decimal result, e.g. with 2 floating points, you could use bc and printf "%f" like this:
m=$( bc <<< "scale=2; $s/$n" )
printf "%.2f" "$m"
I am writing a script that takes 2 numbers as an input and uses recursion to power on number to the power of the other, simple exponentiation. However I am new to scripting and cannot figure out where my syntax is errored here.
Here is the script
#!/bin/bash
echo "Enter number: "
read number
echo "Enter power: "
read power
echo "Powering $number to power of $power!"
exp () {
if [ $2 = 1 ]
then
return $1
fi
return $1 * $(exp $1 $2-1 )
}
result=$(exp $number, $power)
echo "Result: $result"
Currently, it kind of freezes, im not sure if I use the parameters correctly (in terms of syntax).
You need $(( )) to force arithmetic evaluation. Then you can do it with return values:
number=2 power=7
exp () {
if [ $2 -eq 1 ]; then return $1; fi
exp $1 $(($2-1))
return $(($1 * $?))
}
exp $number $power; result=$?
echo "Result: $result"
but it's a bad idea, because shells kind of reserve nonzero return values to communicate failure (e.g. the above solution
will "break" set -e).
More idiomatically, you can use stdout:
set -e
number=2 power=7
exp () {
if [ $2 -eq 1 ]; then echo $1; return; fi
echo $(($1 * $(exp $1 $(($2-1)) ) ))
}
result=$(exp $number $power)
echo "Result: $result"
but that's kind of inefficient with all the subshells.
Best to avoid the recursion and simply loop:
number=2 power=7
exp () {
local res=1 i=0;
while [ $i -lt $2 ]; do res=$((res*$1)); i=$((i+1)); done
echo $res
}
exp $number $power
I use awk in the environment variable:
NUMBER_OF_PORTS=`awk /^"number of ports:"/'{print $4}' Config_input.txt`
which returns the value 2.
I try to use this variable in a while loop:
i=1
while (("$i" <= "$NUMBER_OF_PORTS")); do
echo "hello hello $i"
i=$(( $i+1 ))
done
I receive the following error:
-bash: ((: 1 <= : syntax error: operand expected (error token is "<= ")
How can I use the variable as integer and solve this problem?
EDIT
even if I try to do simple operation like:
let cc=$NUMBER_OF_PORTS+0
it does not work. It is something with the fact that the variable holds the awk command. If I set cc=5 and try to implement the while with $cc it works fine.
Example code
echo $NUMBER_OF_PORTS
#i=1
#echo $i
for (( i = 1; i < ${NUMBER_OF_PORTS}; i += 1 ));
do
echo "hello hello $i"
done
the output is:
$ run_auto_config
2
1
: integer expression expected
NUMBER_OF_PORTS is empty. This gives me the same error:
i=1
NUMBER_OF_PORTS=""
while (("$i" <= "$NUMBER_OF_PORTS")); do
echo "hello hello $i"
i=$(( $i+1 ))
done
Your awk command looks very awkward. Try this:
NUMBER_OF_PORTS=$(awk '/^number of ports:/ {print $4}' Config_input.txt)
Are you sure the string "number of ports:" appears in your text file? Is there a space after the colon?
A couple of comments about your while-loop: ((...)) is arithmetic evaluation, so you don't need strings in there. Also, bare variable names (without the $) is ok, so you can write a bit more elegantly:
while (( i <= NUMBER_OF_PORTS )); do
echo "hello hello $i"
(( i++ ))
done
Update: Based on your comment, try this:
NUMBER_OF_PORTS=$(awk -v RS='\r\n' '/^number of ports:/ {print $4}' Config_input.txt)
change your while line to:
while [ $i -le $NUMBER_OF_PORTS ]; do
then try
You can also replace the while loop by a for loop:
for (( i = 1; i <= ${NUMBER_OF_PORTS}; i += 1 ));
do
echo "hello hello $i"
done
I am a beginner at shell programming. I have a problem related to nested loops in shell scripts. I want to get output like this:
Input: 4
Output:
*
**
***
****
This is the script I am using so far:
echo "input : "
read a
for ((i=0; i<a; i++))
do
for ((j=0; j<i; j++))
do
echo "*"
done
echo "\n"
done
When trying to execute my program I get an error: Bad for looping.
Thanks in advance.
try this
echo "input : "
read a
for ((i=0; i<a; i++))
do
for ((j=0; j<=i; j++))
do
printf "*"
done
echo
done
To not print newlines, you can use printf (or the echo -n but is not as portable as printf)
I don't get any error with the script! Though the echo needs to be different like below:
echo "input : "
read a
for ((i=0; i<a; i++))
do
for ((j=0; j<i; j++))
do
echo -ne "*"
done
echo -ne "\n"
done
You might try adding $ in front of the variables while accessing them though.
It is not giving any errors for me.
#!/bin/bash
print_starry_row()
{
n="$1"
for ((i=0;i<n;i++))
{
echo -n "*"
}
echo
}
read -p "Enter number of stars? " num
if [[ "$num" -eq $num ]]
then
for ((i=1;i<=num;i++))
{
print_starry_row $i
}
else
echo "You must enter a valid integrer"
fi