I’ve a shell script which need to provide the following pattern in the txt file
test0000 test0000#gmail.com
test0001 test0001#gmail.com
and so on until the stop condition (10 in this case...)
currently its not working and I tried with the following:
start=“test”
email=“#gmail.com"
start=0
stop=10
i=0
while [[ $i -le 10 ]]
do
printf "%s%10d\n" "$start” "$i" "\n" "$start” "$email"
any idea how to resolve it ? I got error: "#gmail.com:" invalid number
One more example with a different for loop syntax:
start="test"
email="#gmail.com"
for i in {0000..9};do
echo "${start}$i ${start}${i}${email}"
done
test0000 test0000#gmail.com
test0001 test0001#gmail.com
test0002 test0002#gmail.com
test0003 test0003#gmail.com
test0004 test0004#gmail.com
test0005 test0005#gmail.com
test0006 test0006#gmail.com
test0007 test0007#gmail.com
test0008 test0008#gmail.com
test0009 test0009#gmail.com
Or, with while loop:
start="test"
email="#gmail.com"
count=0
while [[ $count -lt 10 ]]; do
printf '%s%04d %s%04d%s\n' "$start" $count "$start" $count "$email"
let count++
done
You can use:
start='test'
email='#gmail.com'
for ((i=0; i<10; i++)); do
printf '%s%04d %s%04d%s\n' "$start" $i "$start" $i "$email"
done
test0000 test0000#gmail.com
test0001 test0001#gmail.com
test0002 test0002#gmail.com
test0003 test0003#gmail.com
test0004 test0004#gmail.com
test0005 test0005#gmail.com
test0006 test0006#gmail.com
test0007 test0007#gmail.com
test0008 test0008#gmail.com
test0009 test0009#gmail.com
Related
I am novice to linux scripting. For the below example, i need to split the string as per "-" and store the output in an array as a separate element.
Later, i need to validate each element in an array if its an integer or alphanumeric. if its integer, i need to ignore that element and print only non-integer elements. The following script which i am trying is not giving expected output which should be like 'grub2-systemd-sleep-plugin'.
item = grub2-systemd-sleep-plugin-2.02-153.1
IFS='-'
read -rasplitIFS<<< "$item"
for word in "${splitIFS[#]}"; do echo $word; done
Taking a stab at this here...
Depends on how your numbers may be defined, but I believe you could use something like this to removing numbers from the output. I'm not sure if there is a more efficient way to achieve this
for word in ${splitIFS[#]}
do
c=$(echo $word | grep -c -E "^[0-9]+\.{0,}[0-9]+$")
[ $c -eq 0 ] && echo $word
done
If you're using bash, it will be faster if you use built-in tools rather than subshells.
line=grub2-systemd-sleep-plugin-2.02-153.1-foo-1
while [[ -n "$line" ]]
do if [[ "$line" =~ ^[0-9.]+- ]]
then line="${line#*-}"
elif [[ "$line" =~ ^[0-9.]+$ ]]
then break
elif [[ "$line" =~ ^([[:alnum:]]+)- ]]
then echo "${BASH_REMATCH[1]}";
line="${line#*-}"
elif [[ "$line" =~ ^([[:alnum:]]+)$ ]]
then echo "${BASH_REMATCH[1]}";
break
else echo "How did I get here?"
fi
done
or if you prefer,
shopt -s extglob
line=grub2-systemd-sleep-plugin-2.02-153.1-foo-1
while [[ -n "$line" ]]
do case "$line" in
+([0-9.])-*) line="${line#*-}" ;;
+([0-9.])) break ;;
+([[:alnum:]])-*) echo "${line%%-*}"
line="${line#*-}" ;;
+([[:alnum:]])) echo "$line"
break ;;
*) echo "How did I get here?" ;;
esac
done
I have this script which supposed to read file with numbers in each line, and show the largest number, the smallest one and the sum. During the loop variables change their values but after they return their primary value and I can't fix it.
#!/bin/bash
if [ ! $# -eq 1 ]; then
echo "Invalid number of arguments"
elif [ ! -e $1 ]; then
echo "File doesn't exist"
elif [ ! -s $1 ]; then
echo "File is empty"
else
min=$(head -1 $1)
max=$(head -1 $1)
sum=0
(while read i; do
(( sum+=i ))
if [ $min -gt $i ]; then
min=$i
elif [ $max -lt $i ]; then
max=$i
fi
done
)<$1
fi
echo $min $max $sum
(while read i; do
(( sum+=i ))
if [ $min -gt $i ]; then
min=$i
elif [ $max -lt $i ]; then
max=$i
fi
done
)<$1
The subshell introduced by surrounding the loop with ( ) parentheses causes all the variable modifications inside to be confined to the subshell. A subshell is a child process and child processes have their own copies of variables separate from the parent process's.
while read i; do
(( sum+=i ))
if [ $min -gt $i ]; then
min=$i
elif [ $max -lt $i ]; then
max=$i
fi
done <$1
The subshell's not doing anything useful so the easy solution is to remove it.
I changed the expression in top line of loop to cat $1|while read i and removed brackets but it didn't help.
Pipelines have the same problem as subshells: the left and right sides run in child processes. Stick with the while ... done <file version with no pipeline and no subshell.
The problem is that in Bash, parentheses create a new subshell.
You're creating the variables in that subshell, and those variables go away when the subshell finishes.
$ i=foo; (i=bar; echo $i); echo $i
bar
foo
If you remove the parens from your loop, it works:
while read i; do
(( sum+=i ))
if [ $min -gt $i ]; then
min=$i
elif [ $max -lt $i ]; then
max=$i
fi
done < $1
I need some help in my shell script. I have this:
#!/bin/bash
for i in $*
do
if [[ $i = *[a-zA-Z] ]]
then echo $i contains just letters.
elif [[ $i = *[a-zA-Z0-9] ]]
then echo $i contains numbers and letters.
else
echo Error.
done
I would like the result to be, for example:
$ ./script.sh abCd a9d a-b
abCd contains just letters.
a9d contains numbers and letters.
Error.
But I get contains just letters in every case.
I also tried grep command too, but without success.
Your RegEx are wrong. Try the following:
#!/bin/bash
for i in $*
do
if [[ $i =~ ^[a-zA-Z]+$ ]]
then echo $i contains just letters.
elif [[ $i =~ ^[a-zA-Z0-9]+$ ]]
then echo $i contains numbers and letters.
else
echo Error.
fi
done
I am trying to figure out the syntax for having a while loop and an if statement that checks for more than one condition, in a single-line shell script.
Executing something like this...
i=2; while [ $i -le 10 ]; do if [ $i -ne 3 -a $i -ne 5 ] echo $i " not equal to 3 or 5"; else echo $i; i=`expr $i + 1`; done
...I get the error
bash: syntax error near unexpected token `else'
On another hand if I remove the semicolon from between ...3 or 5" and else echo..., and try something like this...
i=2; while [ $i -le 10 ]; do if [ $i -ne 3 -a $i -ne 5 ] echo $i " not equal to 3 or 5" else echo $i; i=`expr $i + 1`; done
...then I get the error:
syntax error near unexpected token `done'
This is on an Ubuntu 14.04, in case it matters.
Am I perhaps missing some kind of a parenthesis somewhere, or is it something else?
This should work:
i=2; while [ $i -le 10 ]; do if [ $i -ne 3 -a $i -ne 5 ]; then echo $i " not equal to 3 or 5"; else echo $i; fi; i=`expr $i + 1`; done
and this should also work:
i=2; while [ $i -le 10 ]; do [ $i -ne 3 -a $i -ne 5 ] && echo "$i not equal to 3 or 5" || echo $i; i=$((i+1)); done
But I am not sure if it makes sense to write this in only one line
You still need a then, and a fi, and enough semicolons.
i=2; while [ $i -le 10 ]; do if [ $i -ne 3 -a $i -ne 5 ]; then echo "$i not equal to 3 or 5"; else echo $i; fi; i=$(expr $i + 1); done
The replacement of back-quotes `…` with $(…) is just a general good idea, not crucial to this discussion.
If written out conventionally on multiple lines (without semicolons), you'd have:
i=2
while [ $i -le 10 ]
do
if [ $i -ne 3 -a $i -ne 5 ]
then echo "$i not equal to 3 or 5"
else echo $i
fi
i=$(expr $i + 1)
done
To convert that to a single line, you need a semicolon after each statement and condition:
i=2;
while [ $i -le 10 ];
do
if [ $i -ne 3 -a $i -ne 5 ];
then echo "$i not equal to 3 or 5";
else echo $i;
fi;
i=$(expr $i + 1);
done
And now the white space (including newlines) can be replaced by single spaces on a single line.
And you could use i=$(($i + 1)) or even (in Bash) ((i++)) in place of expr, which avoids the use of the external command expr; the shell does the arithmetic internally.
I don't think there is a good reason to flatten the script onto one line.
Each if needs a then and fi:
i=2; while [ $i -le 10 ]; do if [ $i -ne 3 -a $i -ne 5 ] ; then echo $i " not equal to 3 or 5" ; else echo $i; i=`expr $i + 1`; fi ; 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