I have a problem regarding about the syntax on how to swap the element value in an array.
array="5 3 2 1 4"
echo "${array[*]}"
changed=1
while [ $changed != 0 ]
do
changed=0
for (( i=0 ; i<=${#array[#]}-1 ; i++ ))
do
if [ ${array[$i]} -gt ${array[$i+1]} ]
then
tmp=${array[$i]}
array[$i]=${array[$i+1]}
array[$i+1]=$tmp
changed=1
fi
done
done
echo "Sorted array: "
echo "${array[*]}"
Edit:
Thanks for answering my question. I have changed the code, and now and it looks something like this.
But unfortunately there is still a problem.
It says:
jdoodle.sh: line 3: $'\r': command not found
jdoodle.sh: line 8: syntax error near unexpected token `$'\r''
jdoodle.sh: line 8: ` for ((i=0;i<=${#array[#]}-1;i++))
This is one implementation of bubble sort:
#!/bin/bash
array=(5 3 2 1 4)
echo "${array[*]}"
size=${#array[#]}
for (( i=0; i<size-1; i++ )); do
for (( j=0; j<size-i-1; j++ )); do
if (( array[j] > array[j+1] )); then
tmp=${array[j]}
array[j]=${array[j+1]}
array[j+1]=$tmp
fi
done
done
echo "Sorted array:"
echo "${array[*]}"
Major problem with your code is that it actually does not use arrays.
Define arrays like array=(value1 value2 value3). It's also better to use [[ ]] for testing instead of [ ]. If we were to change your code just a little to also create a functioning bubble sort algorithm, it could look like this:
#!/bin/bash
array=(5 3 2 1 4)
echo "${array[*]}"
changed=1 j=0
while [[ $changed != 0 ]]
do
((j++))
changed=0
for (( i=0; i<${#array[#]}-j; i++ ))
do
if [[ ${array[i]} -gt ${array[i+1]} ]]
then
tmp=${array[i]}
array[i]=${array[i+1]}
array[i+1]=$tmp
changed=1
fi
done
done
echo "Sorted array:"
echo "${array[*]}"
I do not get the \r messages, even in your test environment; in general, they are a result of DOS/Windows combatability (with a b).
Since this is obviously a tutorial example (why else would someone do bubblesort), some remarks about the code.
array="5 3 2 1 4"
does not create the array that you want. It creates a string. What you are looking for is:
array=(5 3 2 1 4)
The last element of the array is ${#array[#]}-1. Element counting starts at 0. So your for-loop should be:
for (( i=0 ; i<=${#array[#]}-2 ; i++ ))
-2 because you're referencing ${array[$i+1]}, which would otherwise be outside the boundary.
Related
thanks for your help.
What a I doing wrong, here ? I want the numeric answer to be used in a loop but it does not return what I expected :
if [ "$#" -eq 0 ]; then
echo -n "Enter the number: "
read answer
else
answer=( "$#" )
fi
for i in {1..$answer} ; do echo ${i}; done
When executed, I have this:
me#local misc]$ ./test.sh
Enter the number: 5
{1..5}
I expected the echo to return 1 2 3 4 5
You can also do it like:
if [ "$#" -eq 0 ]; then
echo -n "Enter the number: "
read answer
else
answer=( "$#" )
fi
for i in $(seq 1 $answer) ; do echo ${i}; done
With no proposed answer I decided to switch to bash with that syntax that works (though it bothers me)
for (( i=1 ; i<=${answer} ; i++));
I'm having a problem where I am trying to use bubble sort in shell, I am not really sure where my problem is occurring as I am assuming that my sorting is correct. I am not getting an error but I am not sorting the numbers at all.
#!/bin/bash
array=( "$#" )
#echo ${array[#]} print all elements in the array
if [ $# -gt 9 ]
then
echo Too many arguments, run the program over again
exit
fi
j=0
flag=1
a=${#array[#]}
for((j=0;j < $a - 1 && flag==1 ;j++))
do
flag=0
for((i=0; i< $a-j-1; i++))
do
x=${array[$i]}
y=${array[$i+1]}
if ((x>y))
then
flag=1
export temp=$x
export x=$y
export y=$temp
fi
done
done
echo "Sorted Array: " ${array[#]}
As pointed out in the comments, you swap the variables x and y but never any array entries. Instead of
x=${array[$i]}
y=${array[$i+1]}
if ((x>y)); then
flag=1
export temp=$x
export x=$y
export y=$temp
fi
write
x=${array[$i]}
y=${array[$i+1]}
if ((x>y)); then
flag=1
array[$i]="$y"
array[$i+1]="$x"
fi
The main goal of this program is to simulate the drawing of a card as many times as the user chooses and then print out a histogram using '*' to represent the number of hits on each card. However, the problem that I am having is retrieving the elements in each array and printing the stars that correlates with them. This is what I have so far:
timelimit=5
echo -e "How many trials would you like to run? \c"
read -t $timelimit trials
if [ ! -z "$trials" ]
then
echo -e "\nWe will now run $trials trials"
else
trials=10
echo -e "\nWe will now run the default amount of trials: $trials"
fi
count=1
MAXCARD=53
declare -a CARDARRAY
while [ "$count" -le $trials ]
do
card=$RANDOM
let "card %= MAXCARD"
let "CARDARRAY[$card] += 1"
let "count += 1"
done
echo ${CARDARRAY[#]}
for (( i=0; i<${#CARDARRAY[#]}; i++));
do
#declare "temp"="${CARDARRAY[$i]}"
#echo "$temp"
#for (( j=0; j<temp; j++));
#do
#echo "*"
#done
echo "$i"
done
Obviously the last for loop is where I'm having trouble and is currently the latest attempt at printing the stars according to how many hits each card has.
You were pretty close. Here's how I'd paraphrase your script:
#!/bin/bash
timelimit=5
printf %s 'How many trials would you like to run? '
read -t $timelimit trials
if [[ ! -z $trials ]] ; then
printf '\nWe will now run %d trials\n' $trials
else
trials=10
printf '\nWe will now run the default amount of trials: %d\n' $trials
fi
count=1
MAXCARD=53
declare -a CARDARRAY
while (( trials-- )) ; do
(( CARDARRAY[RANDOM % MAXCARD] += 1 ))
done
printf '%s\n' "${CARDARRAY[*]}"
for (( i=0 ; i<MAXCARD ; i++ )) ; do
printf %02d: $i
for (( j=0 ; j<${CARDARRAY[i]:-0} ; j++ )) ; do
printf %s '*'
done
printf '\n' ''
done
You can use set -xv to see what bash is running at each step.
Consider the ideal array to be :
0 1 2 3 4 5
Say the array that i get during one execution:
0 1 3 5
My script should display 2 and 4 are missing .
My code so far:
#!/bin/bash
## declare an array variable
a=`cat read/Array/values/from file/`
declare -a simpleArray=( $a )
# get length of an array
arraylength=${#simpleArray[#]}
j=0
while [ $j -lt $arraylength ]
do
# use for loop to read all values and indexes
for ((i=1;i< ${arraylength}+1;i++));
do
y=${simpleArray[$i-1]}
echo $y'current value'
if [ y == j ]
then
echo 'present'
else
echo $j'not present'
j=$((j+1))
fi
done
echo 'for loop close'
done
echo 'while loop close'
EDIT Code
#!/bin/bash
a=`cat /home/muzammilm/textdate.txt`
simpleArray=( 1 2 6 )
j=0;
i=0;
arraylength=${#simpleArray[#]}
echo $arraylength
while [ $j != 6 ]
do
for (( i=0; i< $arraylength; i++ ))
do
if [ ${simpleArray[$i]} = $j ]
then
break
elif [ ${simpleArray[$i]} > $j ]
then
echo $j'not present'
break;
fi
done
j=$((j+1))
done
This gives me an error,though it works perfectly when the ip array contain only two elements
This test is always false:
if [ y == j ]
because it is a string comparison of constant strings "y" and "j". Did you mean
if [ $y = $j ]
instead? (Yes, only one = sign is the correct test for equality).
I have this code to get all the lines filtered by the expression used the grep:
arrvar=( $(grep -Poh '^[A-Z_]+=.+' input.txt) )
arrlen=${#arrvar[#]}
i=0
while : ; do
split=(${arrvar[i]//=/ })
name="${split[0]}"
value="${split[1]}"
echo "index..: $i"
echo "name...: $name"
echo "value..: $value"
i=$(( i + 1 ))
if [ $i > $arrlen ]; then
break
fi
done
Whit this content in input.txt:
HELLO=111
STACK=222
OVERFLOW=333
The result is the following:
index..: 0
name...: STACK
value..: 222
Why only returns the first item of the array instead the three of the file?
You are testing like this:
if [ $i > $arrlen ]
but you probably mean
if (( i > arrlen ))
[ compares lexicographically while (( compares numerical.