How to progress the echo from 1 to 100% in bash in given time? - bash

Iam using a bash script which i want to show a timer before my next function should called.So instead of regular sleep 5 i wanted to use some progress bar.So from stackoverflow I found this snippet.
for pc in $(seq 1 10); do
echo -ne "$pc%\033[0K\r"
sleep 1
done
But this only shows 1 to 10% in 10 seconds . But all I need is to move the progress bar from 1 to 100 in 10 Seconds like 0 10 20 ... 90 100 Just like the above script.
Any suggestions will help.

for pc in $(seq 0 10 100); do
echo -ne "$pc%\033[0K\r"
sleep 1
done
This will start from 0 and proceed to 100 with steps of 10

Related

How do I create a bash script, using loops, to create a Multiplication Table with 5 column/10 row format

Here is what I have:
#!/bin/bash
#create a multiplication table 5 columns 10 rows
echo " Multiplication Table "
echo "-----+-------------------------"
for x in {0..5}
do
for y in {0..10}
do
echo -n "$(( $x * $y )) "
done
echo
echo "-----+--------------------------"
done
This is my Output:
Multiplication Table
-----+-------------------------
0 0 0 0 0 0 0 0 0 0 0
-----+--------------------------
0 1 2 3 4 5 6 7 8 9 10
-----+--------------------------
0 2 4 6 8 10 12 14 16 18 20
-----+--------------------------
0 3 6 9 12 15 18 21 24 27 30
-----+--------------------------
0 4 8 12 16 20 24 28 32 36 40
-----+--------------------------
0 5 10 15 20 25 30 35 40 45 50
-----+--------------------------
This is the Needed Output:
Multiplication Table
----+-------------------------------------
| 0 1 2 3 4
----+-------------------------------------
0 | 0 0 0 0 0
1 | 0 1 2 3 4
2 | 0 2 4 6 8
3 | 0 3 6 9 12
4 | 0 4 8 12 16
5 | 0 5 10 15 20
6 | 0 6 12 18 24
7 | 0 7 14 21 28
8 | 0 8 16 24 32
9 | 0 9 18 27 36
----+-------------------------------------
I've tried to write this many different ways, but I'm struggling with finding a way to format it correctly. The first is pretty close, but I need it to have the sequential numbers being multiplied on the top and left side. I'm not sure how to use, or if I can use, the seq command to achieve this or if there is a better way. I also need to have straight columns and rows with the defining lines setting the table layout, but my looking up the column command hasn't produced the right output.
Here was my final output and code:
#!/bin/bash
#create a multiplication table 5 columns 10 rows
#Create top of the table
echo " Multiplication Table"
echo "----+------------------------------"
#Print the nums at top of table and format dashes
echo -n " |"; printf '\t%d' {0..5}; echo
echo "----+------------------------------"
#for loops to create table nums
for y in {0..9}
do
#Print the side nums and |
echo -n "$y |"
#for loop to create x
for x in {0..5}
do
#Multiply vars, tab for spacing
echo -en "\t$((x*y))"
done
#Print
echo
done
#Print bottom dashes for format
echo "----+------------------------------"
I changed a bit of Armali's code just to make it more appealing to the eye, and the echo was moved to the bottom (out of the loop) so it didn't print as many lines. But again, thank you Armali, as I would've spent a lot more time figuring out exactly how to write that printf code to get the format correct.
I'm not sure how to use, or if I can use, the seq command to achieve this …
seq offers no advantage here over bash's sequence expression combined with printf.
This variant of your script produces (with the usual 8-column tabs) the needed output:
#!/bin/bash
#create a multiplication table 5 columns 10 rows
echo " Multiplication Table"
echo "----+-------------------------------------"
echo -n " |"; printf '\t%d' {0..4}; echo
echo "----+-------------------------------------"
for y in {0..9}
do echo -n "$y |"
for x in {0..4}
do echo -en "\t$((x*y))"
done
echo
echo "----+-------------------------------------"
done

Referencing one number to another number

I have a question which I think is fairly simply but I am new to Bash and can't find much info on this.
5 references 3
10 references 4
20 references 10
30 references 20
inputBeforeLookup = 5 #this the number which needs to look up 3 above^^^^
# 10 would lookup and return 4
#20 returns 10
start = 1
end = $start + $lookupNumberfromFile # 3 in this case, since input was 5
seq $start $end
1
2
3
4
I guess my question here is what is the proper way to create like a configuration file which references numbers to other numbers?
If there is a better way than the snippet of code I posted I am always open to suggestions, like i said I am learning.
I am new to this so I am not sure if the syntax is 100% correct. I am more so looking for a solution on the best way to solve the problem.
Hope this sample helps you regarding variable expansion in bash:
Notice that: the \ prevents the expansion of $$ (current process id). For triple substitution you need double eval and so on....
#!/bin/bash
one=1
two=one
three=two
four=three
five=four
echo $one
eval echo \$$two
eval eval echo \\$\$$three
eval eval eval echo \\\\$\\$\$$four
eval eval eval eval echo \\\\\\\\$\\\\$\\$\$$five
Output:
1
1
1
1
1
Bonus:
In zsh you can use nested substitution much more easily:
#!/bin/zsh
one=1
two=one
three=two
four=three
five=four
echo $one
echo ${(P)two}
echo ${(P)${(P)three}}
...
http://zsh.sourceforge.net/Doc/Release/Expansion.html
Set up an associative array, then test it with numbers 1 to 30. Those numbers that don't reference other numbers are printed as is:
MYMAP=( [5]=3 [10]=4 [20]=10 [30]=20 )
seq 30 | while read x ; do echo ${MYMAP[$x]:-$x} ; done | paste - - - - -
That last | paste - - - - - isn't necessary, but 5 column output is easier to follow given that the input has several multiples of 5. Output:
1 2 3 4 3
6 7 8 9 4
11 12 13 14 15
16 17 18 19 10
21 22 23 24 25
26 27 28 29 20

bash search output for similar text and perform calculation between the 2

I am working on a script that will run a pm2 list and assign it to a variable, wait X seconds and run it again assigning it to a different variable. Then I run those through a comm <(echo "$pm2_1") <(echo "$pm2_2") -3 that gives me only the output that is different between the 2 in a nice format
name ID restart count
prog-name 0 1
prog-name 0 2
prog-name-live 10 1
prog-name-live 10 8
prog-name-live 3 1
prog-name-live 3 4
prog-name-live 6 1
prog-name-live 6 6
What I need is a way to compare the restart counts on the 2 lines with similar IDs.. EX
name ID restart count
prog-name 0 1
prog-name 0 2
prog-name-worker 10 1
prog-name-worker 10 8
Any ideas would be very helpful!
Thanks
awk supports hash hope that helps
awk '{k=$1" "$2; a[k]=$3; print k, a[k]}'
here is example of using it to find difference, you can try any logic
awk '{k=$1" "$2; if (a[k]==0)a[k]=$3; else {a[k]-=$3; q=a[k]>0?a[k]:a[k]*-1;print k,q}}'

Nested For loop counter reset

I'm trying to run nested for loops that use lists as their loop counters. The problem is that once the 'delta' loop reaches 100, it doesnt reset to 0. Same problem for 'edges'.
I tried this, but it doesnt seem to work for my loops.
http://tldp.org/LDP/abs/html/nestedloops.html
Any ideas here? Here's my code:
#!/bin/sh
threads="1 2 4 8 16 32 64 96 128 160 192 224 256"
delta="0 10 20 30 40 50 60 70 80 90 100"
edges="16 8192"
nodes="16384"
for threads in $threads
do
for delta in $delta
do
for edges in $edges
do
for nodes in $nodes
do
printf "\n"
echo $threads
echo $delta
echo $edges
echo $nodes
done
done
done
done
expected output:
1 0 16 16384
1 0 8192 16384
1 10 16 16384
1 10 8192 16384
1 20 16 16384
1 20 8192 16384
When using for loops like this, make sure you give the loop variable a different name than the variable you are iterating over.
Using for threads in $threads makes it confusing to distinguish between the looping variable (threads) and the thing you're looping over ($threads).
When you call echo $threads later, bash doesn't know you're referring to the first one.
In this case, you could change the loop declarations to something like for n in nodes or for t in threads, then echo out $n and $t inside the innermost loop to obtain the desired output.

bash 'while read line' efficiency with big file

I was using a while loop to process a task,
which read records from a big file about 10 million lines.
I found that the processing become more and more slower as time goes by.
and I make a simulated script with 1 million lines as blow, which reveal the problem.
but I still don't know why, how does the read command work?
seq 1000000 > seq.dat
while read s;
do
if [ `expr $s % 50000` -eq 0 ];then
echo -n $( expr `date +%s` - $A) ' ';
A=`date +%s`;
fi
done < seq.dat
The terminal outputs the time interval:
98 98 98 98 98 97 98 97 98 101 106 112 121 121 127 132 135 134
at about 50,000 lines,the processing become slower obviously.
Using your code, I saw the same pattern of increasing times (right from the beginning!). If you want faster processing, you should rewrite using shell internal features. Here's my bash version:
tabChar=" " # put a real tab char here, of course
seq 1000000 > seq.dat
while read s;
do
if (( ! ( s % 50000 ) )) ;then
echo $s "${tabChar}" $( expr `date +%s` - $A)
A=$(date +%s);
fi
done < seq.dat
edit
fixed bug, output indicated each line was being processed, now only every 50000'th line gets the timing treatment. Doah!
was
if (( s % 50000 )) ;then
fixed to
if (( ! ( s % 50000 ) )) ;then
output now echo ${.sh.version} = Version JM 93t+ 2010-05-24
50000
100000 1
150000 0
200000 1
250000 0
300000 1
350000 0
400000 1
450000 0
500000 1
550000 0
600000 1
650000 0
700000 1
750000 0
output bash
50000 480
100000 3
150000 2
200000 3
250000 3
300000 2
350000 3
400000 3
450000 2
500000 2
550000 3
600000 2
650000 2
700000 3
750000 3
800000 2
850000 2
900000 3
950000 2
800000 1
850000 0
900000 1
950000 0
1e+06 1
As to why your original test case is taking so long ... not sure. I was surprised to see both the time for each test cyle AND the increase in time. If you really need to understand this, you may need to spend time instrumenting more test stuff. Maybe you'd see something running truss or strace (depending on your base OS).
I hope this helps.
Read is a comparatively slow process, as the author of "Learning the Korn Shell" points out*. (Just above Section 7.2.2.1.) There are other programs, such as awk or sed that have been highly optimized to do what is essentially the same thing: read from a file one line at a time and perform some operations using that input.
Not to mention, that you're calling an external process every time you're doing subtraction or taking the modulus, which can get expensive. awk has both of those functionalities built in.
As the following test points out, awk is quite a bit faster:
#!/usr/bin/env bash
seq 1000000 |
awk '
BEGIN {
command = "date +%s"
prevTime = 0
}
$1 % 50000 == 0 {
command | getline currentTime
close(command)
print currentTime - prevTime
prevTime = currentTime
}
'
Output:
1335629268
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
Note that the first number is equivalent to date +%s. Just like in your test case, I let the first match be.
Note
*Yes the author is talking about the Korn Shell, not bash as the OP tagged, but bash and ksh are rather similar in a lot of ways. ksh is actually a superset of bash. So I would assume that the read command is not drastically different from one shell to another.

Resources