how to generate sequence of ones and zeros in bash script - linux

I am trying to generate a sequence of ones and zeros in using bash script.
#!/bin/bash
clock=1
n=1
# continue until $n equals 5
while [ $n -le 5 ]
do
echo "$clock"
n=$(( n+1 )) # increments $n
clock=$(~clock)
done
Expected output:
1
0
1
0
1
Output generated from the above code:
I am getting error from this line: clock=$(~clock)
Error: ~clock: command not found

If you want to generate sequence with 1 and 0 alternatively, you can use
#!/bin/bash
clock=1
n=1
# continue until $n equals 5
while [ $n -le 5 ]
do
echo "$clock"
n=$(( n+1 ))
# increments $n
clock=$((clock+1))
clock=$((clock%2))
done
If you want to generate random sequence of 1 and 0s, you can use
#!/bin/bash
n=1
# continue until $n equals 5
while [ $n -le 5 ]
do
echo "$((RANDOM%2))"
n=$(( n+1 ))
done

Problem is in this line:
clock=$(~clock)
Here bash is trying to run anything inside $(...) as a command (it is called command substitution).
Using ~clock is also incorrect as it will only do bitwise negation and will not produce 1 and 0 as you are expecting.
You can use this script to get alternate 1 and 0 printed:
#!/bin/bash
clock=1
# continue until $n equals 5
for ((n=0; n<5; n++))
do
echo "$clock"
clock=$((1 - clock))
done

Another short way to do it
#!/bin/bash
for i in {1..5}
do
echo $((i%2))
done
Or slightly less concise but easier to configure with variables to define the loop :
#!/bin/bash
for ((i=1;i<=5;i++))
do
echo $((i%2))
done
Another one, just for fun (would not do that in a read script, more like a little puzzle to figure out why it works). Remove the "false" line to begin with 0.
#!/bin/bash
false
for i in {1..5}
do
echo $? ; [[ $_ != 0 ]]
done

You can utilize the following trick using the brace expansion.
echo {,,,,}{1,0}
This one will generate 5 pairs of ones and zeroes.

Related

Fibonacci sequence calculator

I have an issue with some homework, so basically we were asked to create a bash script that takes a variable greater than 2 and gives back the same number of Fibonacci sequence numbers, i.o. if i were to give 5 it would print:
0 1 1 2 3
I have done some research and have come up with a unique idea i havent really seen anywhere online, (keep in mind i have some experience in python) but i have run into a problem, so basically i use a for expression in bash and 2 variables to calculate the sequence, i first manually set them to be 0 and 1 (the first and second numbers in the sequence) and then i add them together while changing their values,
So here is the code :
#!/bin/bash
a=0
b=1
for i in $(seq 1 $1);
do
if ["$a" -gt "$b"]
then
b=($a +$b)
echo "$b"
else
a=($a +$b)
echo $a
fi
done
I have many issues and expect to be completely out of context but i hope you get the general idea and can help guide me through the problem :/
It seems like i want something to be treated as a number but its treated as text... Not sure though, any help is highly appreciated
You were very close, some small syntactic changes and new initial values make it work.
Notes:
whitespace is important in bash, especially with special characters [ ] ;
also, calculation with integer number can be forced using let
Nice idea to use a comparison to do the calculation with just two variables :)
#!/bin/bash -
a=1
b=0
echo $a
for i in $(seq 1 $1);
do
if [ $a -gt $b ] ; then
let b=($a +$b)
echo $b
else
let a=($a +$b)
echo $a
fi
done
there is an arithmetic context in bash.
slight re-write can be
$ a=0; b=1;
for i in {1..9};
do c=$((a+b));
echo $c;
if ((a>b)); then b=$c; else a=$c; fi;
done
1
2
3
5
8
13
21
34
55
You need a space
if [ "$a" -gt "$b" ]
and you can do arithmetic evaluation using
b=$((a+b))
once the script runs, verify the result is what you are expecting (i.e. does it print 0?)
Use double parens to evaluate arithmetic expressions. Instead of:
if [ "$a" -gt "$b" ]
write:
if ((a > b))
and instead of:
($a + $b)
write:
$((a + b))
You can also write the for header this way:
for ((i = 0; i < $1; i++))
But this is not required in this case. Your loop then becomes:
for ((i = 0; i < $1; i++)); do
if ((a > b)); then
b=$((a + b))
echo "$b"
else
a=$((a + b))
echo "$a"
fi
done
#!/bin/bash
a=0
b=1
echo $a
c=$1
for i in $(seq 1 $((c-1)));
do
if [ $a -gt $b ]; then
b=$((a+b))
echo $b
else
a=$((a+b))
echo $a
fi
done

Bash script add numbers as received in arguments

The requirement is that when the script is called as below:
my_script.sh 1 2 3 4
The script should be able to add these numbers and print sum at the end.
num=0
for arg in "$#"
do
for number in $arg
do
(( num += $number ))
done
done
I've written the script as above but not getting the desired output.
Your script doesn't output anything. Try adding
echo $num
at the end.
BUT your script can be simplified. As written, your script would work for input like
my_script.sh 1 '2 3' 4
as well, as it first loops over the arguments (for arg in "$#"), but then also loops over all the words in each argument (for number in $arg). You don't need the second loop.
Also, naming the result $sum seems to better explain its purpose. So, you can just type
#!/bin/bash
sum=0
for number in "$#" ; do
(( sum += number ))
done
echo $sum

Finding numbers in file (script, bash)

I want to find number or words in file. As first parameter it gets file name and second number you are looking for.
For example I write in command line:
bash script.sh file.txt 6
And i get on output
Number 6 repeats 4 time
This is content in file.txt
5 4 5 6 2 4 6 3 6 6
This is the code what I came up and stuck
para2=$2
while read line
do
array=($line)
echo "Value of third element in my array : ${array[3]} "
done < $1
I dont know how to compare parameter 2 with every array. I know that in code above I print out third array but I dont know how to go through every array and compare them with parameter two. I mean i want to go through all numbers and compare with input parameter. Pleas help
Try this:
numOccurences=0
while read line
do
array=($line)
for i in "${array[#]}"
do
if [ "$2" = "$i" ]
then
numOccurences=`expr $numOccurences + 1`
fi
done
done < $1
echo "$2 occurs $numOccurences times in $1"
The program will read a line, iterate through the array formed by the line, and then it will compare the value to the target character. A counter is updated for every match, and the result is printed at the end.
Example input (file.txt):
5 4 5 6 2 4 6 3 6 6 6 6
6 6
᠎
Command:
/Users/Robert/Desktop/Untitled.sh /Users/Robert/Desktop/file.txt 6
Output:
6 occurs 8 times in /Users/Robert/Desktop/file.txt
para2=$2
counter=0
while read line
do
for num in $line
do
if [[ $num -eq $para2 ]]
then let counter = ((counter + 1))
fi
done
done < "$1"
echo Number $para2 repeats $counter times
#!/bin/bash
echo "Number to be searched $2 "
echo "File name passed : $1"
filename=$1
count=0
while read line
do
for word in $line; do
#echo "Number = $word"
if [ "$2" == "$word" ]; then
count=$(expr $count + 1)
fi
done
done < $filename
echo $2 is observed $count times

run shell script with arguments manipulation

I need to get three arguments by test.ksh script
as the following
./test.ksh 12 34 AN
is it possible to set the argument by counter for example ?
for get_arg 1 2 3
do
my_array[get_arg]=$$get_arg
print ${my_array[get_arg]}
done
in this example I want to get three arguments from the user by loop counter "$$get_arg"
in place of $1 $2 $3
is it possible? and how ?
my_array=("$#")
for i in 0 1 2
do
echo "${my_array[$i]}"
done
This assigns all the arguments to array my_array; the loop then selects the first three arguments for echoing.
If you're sure you want the first three arguments in the array, you could use:
my_array=("$1" "$2" "$3")
If you want the 3 arguments at positions 1, 2, 3 in the array (rather than 0, 1, 2), then use:
# One or the other but not both of the two assignments
my_array=("dummy" "$#")
my_array=("dummy" "$1" "$2" "$3")
for i in 1 2 3
do
echo "${my_array[$i]}"
done
bash has a special variable
$#
which contains the arguments of the script it currently executes. I think this is what your'e looking for:
for arg in $# ; do
# code
done
Edit:
My bad ksh:
for arg;do
print $arg
done
Original Post:
Use shift to iterate through shell script parameters:
# cat test.sh
#!/bin/bash
while [ "$1" != "" ]; do
echo $1
shift
done
test run:
# ./test.sh arg1 monkey arg3
arg1
monkey
arg3
source
Even you don't need in $#, this would work the same:
#!/bin/bash
i=0
for arg; do
my_array[i]="$arg"
echo "${my_array[i]}"
(( i++ ))
done
That is,
if in words is not present, the for command executes the commands
once for each positional parameter that is set, as if in $# had been
specified.

grabbing all arguments after nth argument and concatenating them together in bash

So I have a bash script that needs to take an arbitrary number of command line arguments and put them into a single string
Example of what the user would type in:
give <environment> <email> <any number of integers separated by spaces>
give testing stuff#things.com 1 2 3 4 5
I want to get all of the arguments from $3 to $# and concat them into a string.
My (probably awful) solution right now is
if [ $# -gt 3 ]
then
env="env="$1
email="email="$2
entList=""
for i in {3..$#}
do
if [ $i -eq 3 ]
then
entList=$3
shift
fi;
if [ $i -gt 3 ]
then
entList=$entList","$3
shift
fi;
done
fi;
I handle the case of having only three arguments a bit differently, and that one works fine.
Final value of $entList given the example give testing stuff#things.com 1 2 3 4 5 should be: 1,2,3,4,5
Right now when i run this i get the following Errors:
/usr/local/bin/ngive.sh: line 29: [: {3..5}: integer expression expected
/usr/local/bin/ngive.sh: line 34: [: {3..5}: integer expression expected
Lines 29 and 34 are:
line 29: if [ $i -eq 3 ]
line 34: if [ $i -gt 3 ]
Any help would be appreciated.
You're on the right track. Here's my suggestion:
if [ $# -ge 3 ]; then
env="$1"
email="$2"
entlist="$3"
while shift && [ -n "$3" ]; do
entlist="${entlist},$3"
done
echo "entlist=$entlist"
else
echo "Arguments: $*"
fi
Note that variables should always be put inside quotes. I'm not sure why you were setting env=env=$1, but I suspect that if you want to recycle that value later, you should do it programatically rather than by evaluating the variable as if it were a statement, in case that was your plan.
Skip first three arguments using a subarray:
all=( ${#} )
IFS=','
threeplus="${all[*]:3}"
The reason you're getting those error messages is that in:
for i in {3..$#}
The brace expansion is performed before the parameter expansion and so the following if statement is evaluated as:
if [ {3..$#} -eq 3 ]
which isn't valid.
Change your for statement to use the C style:
for ((i = 3; i <= $#; i++))
Use this style for integer comparison:
if (( $# > 3 ))
and
if (( i == 3 ))
and
if (( i > 3 ))
Put your parameters inside the quotes:
env="env=$1"
email="email=$2"
and
entList="$entList,$3"
although the quotes aren't necessary since word splitting isn't performed on the right side of an assignment and you're not assigning special characters such as whitespace, semicolons, pipes, etc.

Resources