Loop in UNIX is not working - bash

Please tell me what is wrong with the UNIX code below.
#!/bin/ksh
p=10
for i in $p
do
echo $i
done
i am expecting output as
1
2
3
.
.
.
but the output am getting is just 10
I need for loop not while loop.

in ksh
#!/bin/ksh
p=10
i=1
while ((i<=p)); do
echo $i
i=$((i+1))
done
or
#!/bin/ksh
# with for you can only do this
for i in 1 2 3 4 5 6 7 8 9 10; do
echo $i
done
in bash it works as expected
#!/bin/bash
p=10
for (( i=1; i<=p; i++ )); do
echo $i
done
there is a Linux command seqthat can be used for both ksh and bash. But it is a Linux command. So this will not work on Solaris or other Unix systems that don't have the progrtam seq installed.
# on Linux, bash or ksh
p=10
for i in $(seq $p); do
echo $i
done
The following uses only shell built-ins and therefore will work for all bash installations (e.g. on Solaris) but not for ksh
#!/bin/bash
p=10
for i in `eval echo {1..$p}`; do
echo $i
done
This complicated construct is necessary because of brace expansion occurrs before variable expansion

You have to assign a range. Otherwise the loop can't work. This should do it:
#!/bin/ksh
p=10
for i in {0..$p}
do
echo $i
done
#fedorqui: You are right, I absolutely missed that. When I do stuff like this in Bash (I don't know if it's the same for KornShell), I go like:
for ((i=0; i<$p; i++))

in UNIX KSH
#!/bin/ksh
while [ ${i:=1} -le 10 ]
do
echo "$i"
let i+=1
done

Related

bash script, to use a variable in a variable

In order to obtain the results of consecutive numbers, a bash script was created as follows.
However, the results did not come out as intended.
#!/bin/bash
test="i am $i"
for i in {1..10}
do
echo "$test"
done
result
sh test.sh
i am
i am
i am
i am
i am
i am
i am
i am
i am
i am
But the result I want is...
As shown below, how do we deal with the variables to get the results?
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
Use $i outside of the variable
#!/bin/bash
test="i am "
for i in {1..10}
do
echo $test $i
done
Also you can use ${i} inside of the variable
#!/bin/bash
for i in {1..10}
do
test="i am ${i}"
echo $test
done
The result is:
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
Or you can replace substr with anything you want inside.
For example
#!/bin/bash
test="I am SUBSTR"
for i in {1..10}
do
echo ${test/SUBSTR/$i}
done
When you have multiple variables, I know this solution:
#!/bin/bash
test="I am SUBSTR and STR2"
for i in {1..10}
do
o=${test/SUBSTR/$i}
echo ${o/STR2/$i*$i}
done
Using sed also can help
#!/bin/bash
test="I am SUBSTR and STR2"
for i in {1..10}
do
echo $test | sed -e 's/SUBSTR/'$i'/;s/STR2/'$i++'/'
done
You need to write a function in order to delay the evaluation.
#!/bin/bash
message () { echo "i am $1"; }
for i in {1..10}
do
message $i
done
Or the following, if you just want to craft the message.
#!/bin/bash
message () { echo "i am $1"; }
for i in {1..10}
do
test="$(message $i)"
echo "$test"
done
#!/bin/bash
test='i am $i'
for i in {1..10}
do
eval echo "$test"
done
or
#!/bin/bash
test='echo "i am $i"'
for i in {1..10}
do
eval "$test"
done
Example:
yanyong#master:~$ test='echo "i am $i"'; for i in {1..10}; do eval "$test"; done
i am 1
i am 2
i am 3
i am 4
i am 5
i am 6
i am 7
i am 8
i am 9
i am 10
References:
https://man7.org/linux/man-pages/man1/eval.1p.html

linux bash script error

when I try to run this script
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
echo –n $i
done
echo " "
done
I get this error:
syntax error near unexpected token '(('
for ((j=1; j<=5; j++))"
It appears you're running this with an interpreter that is not bash. I've indented your code, but it worked just fine without indentation too.
$ cat test.bash
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
echo –n $i
done
echo " "
done
$ /bin/sh test.bash
/tmp/test.bash: 1: Syntax error: Bad for loop variable
$ echo $BASH_VERSION
5.0.11(1)-release
$ bash test.bash
–n 1
–n 1
–n 1
–n 1
–n 1
–n 2
–n 2
…
As you can see, echo -n is not reliable. Change that line to printf %s $i to resolve that and your output will become:
11111
22222
33333
44444
55555
If you are invoking it with bash, perhaps your bash version is too old? You can use for i in {1..5} for something more compatible (but not valid POSIX) or you could use for i in 1 2 3 4 5 for full POSIX compatibility. If you have GNU coreutils, you could do for i in $(seq 5) instead (see man seq).
To better approach your intended logic, you could also consider a while loop:
i=0
while [ $((++i)) -le 5 ]
do
j=0
while [ $((++j)) -le 5 ]
do
printf %s $i
done
echo " "
done
This initializes i to zero before a while loop, then increments it in the test condition when comparing it to five; the first loop's first iteration increments i to 1, finds that it is indeed less than or equal (-le) to 5, and therefore continues.
(I'm using a $((…)) arithmetic expression and ++i inside it since the more common i++ would return the value of i before it is incremented while ++i returns the value of i after it is incremented.)

Increment variable value by 1 (shell programming)

I can't seem to be able to increase the variable value by 1. I have looked at tutorialspoint's Unix / Linux Shell Programming tutorial but it only shows how to add together two variables.
I have tried the following methods but they don't work:
i=0
$i=$i+1 # doesn't work: command not found
echo "$i"
$i='expr $i+1' # doesn't work: command not found
echo "$i"
$i++ # doesn't work*, command not found
echo "$i"
How do I increment the value of a variable by 1?
You can use an arithmetic expansion like so:
i=$((i+1))
or declare i as an integer variable and use the += operator for incrementing its value.
declare -i i=0
i+=1
or use the (( construct.
((i++))
The way to use expr:
i=0
i=`expr $i + 1`
The way to use i++ (unless you're running with -e/-o errexit):
((i++)); echo $i;
Tested in gnu bash.
you can use bc as it can also do floats
var=$(echo "1+2"|bc)
These are the methods I know:
ichramm#NOTPARALLEL ~$ i=10; echo $i;
10
ichramm#NOTPARALLEL ~$ ((i+=1)); echo $i;
11
ichramm#NOTPARALLEL ~$ ((i=i+1)); echo $i;
12
ichramm#NOTPARALLEL ~$ i=`expr $i + 1`; echo $i;
13
Note the spaces in the last example, also note that's the only one that uses $i.

Bourne Shell Building and referencing a variable

I have a shell that runs where the preset env variables include:
FOOCOUNT=4
FOO_0=John
FOO_1=Barry
FOO_2=Lenny
FOO_3=Samuel
I can not change the way I get this data.
I want to run a loop that generates up the variable and uses the contents.
echo "Hello $FOO_count"
This syntax is however wrong and that is what I am searching for...
count=$FOOCOUNT
counter=0
while [ $counter -lt $count ]
do
#I am looking for the syntax for: <<myContructedVar= $ + 'FOO_' + $counter>>
counter=`expr $counter + 1`
echo "Greeting #$counter: Hello, ${myContructedVar}."
done
Thanks very much
The key is eval:
count=$FOOCOUNT
counter=0
while [ $counter -lt $count ]
do
myConstructedVar=FOO_$counter
counter=`expr $counter + 1`
echo "Greeting #$counter: Hello, `eval echo \$${myConstructedVar}`."
done
The loop arithmetic is old school - the way I write the code. Modern shells have more arithmetic built in - but the question is tagged Bourne shell.
You'll need an eval and a deferred sigil:
$ foo_0=john
$ count=0
$ name="\$foo_$count"
$ echo $name
$foo_0
$ eval echo "$name"
john
but unless the index is truly important to you, you might use
for i in "$foo_0" "$foo_1" "$foo_2" ... ; do
...
done
and get rid of the badly named pseudo-array. And, if you have an upper bound on the number of the number of foo_x and there are no special characters in the various foos (in particular no character in $IFS which defaults to <space><tab><return>) then you can use the null-argument collapsing feature of the shell and:
$ for i in $foo_0 $foo_1 $foo_2 ; do
> echo '***' $i
> done
*** john
and allow the shell to ignore unset foo_x
It's been a very long time since I've done any Bourne shell but have you tried the eval command?

Iterating through a range of ints in ksh?

How can I iterate through a simple range of ints using a for loop in ksh?
For example, my script currently does this...
for i in 1 2 3 4 5 6 7
do
#stuff
done
...but I'd like to extend the range way above 7. Is there a better syntax?
Curly brackets?
for i in {1..7}
do
#stuff
done
While loop?
while [[ $i -lt 1000 ]] ; do
# stuff
(( i += 1 ))
done
on OpenBSD, use jot:
for i in `jot 10`; do echo $i ; done;
ksh93, Bash and zsh all understand C-like for loop syntax:
for ((i=1; i<=9; i++))
do
echo $i
done
Unfortunately, while ksh and zsh understand the curly brace range syntax with constants and variables, Bash only handles constants (including Bash 4).
Using seq:
for i in $(seq 1 10)
do
echo $i
done
The following will work on AIX / Linux / Solaris ksh.
#!/bin/ksh
d=100
while (( $d < 200 ))
do
echo "hdisk$d"
(( d=$d+1 ))
done
Optionally if you wanted to pad to 5 places, i.e. 00100 .. 00199 you could begin with:
#!/bin/ksh
typeset -Z5 d
-Scott
Just a few examples I use in AIX because there is no range operator or seq, abusing perl instead.
Here's a for loop, using perl like seq:
for X in `perl -e 'print join(" ", 1..10)'` ; do something $X ; done
This is similar, but I prefer while read loops over for. No backticks or issues with spaces.
perl -le 'print "$_ " for 1..10;' | while read X ; do xargs -tn1 ls $X ; done
My fav, do bash-like shell globbing, in this case permutations with perl.
perl -le 'print for glob "e{n,nt,t}{0,1,2,3,4,5}"' | xargs -n1 rmdev -dl

Resources