BASH Scripting "while loop" - numbers

Write a program using ‘While Loop’ that will accept 6 integers from user
within the range of 6 to 60 and will calculate the Sum of all the inputted
numbers. If the user enters any other value that doesn’t fall into the range of 6-60,
an appropriate error message should be shown, and the program should
ask for input again.

COUNTER=1
sum=0
while [ $COUNTER -lt 7 ]; do
echo Enter value $COUNTER
read value
if [ $value -lt 61 -a $value -gt 7 ]
then
let sum=value+sum
let COUNTER=COUNTER+1
else
echo "Error"
fi
done
echo The sum is $sum

Related

Powershell -replace for perl users: how to replace-match-$1 in PowerShell?

Take a look at this perl code:
$x = "this is a test 123 ... this is only a test"
$x =~ s/"test\s+(\d+)"/"test $1"/
print $x
this is a test 123 ... this is only a test
Notice that I match a number with regex (\d+), it gets put into the temporary variable $1, then it gets put in the output string as an expansion of $1 temporary variable...
Is there a way to do above perl replacement in powershell? I'm thinking if its possible then its something like this??
$x = "this is a test 123 ... this is only a test"
$x = $x -replace "test\s+(\d+)", "test $Matches[1]"
write-host $x
this is a test 123 ... this is only a test
Of course it doesn't work... I was curious how to do this since i have a lot of perl scripts to convert to PowerShell..
Not that different in PowerShell:
$x = "this is a test 123 ... this is only a test"
$x = $x -replace 'test\s+(\d+)', 'test $1'
Write-Host $x
Output:
this is a test 123 ... this is only a test
Regex details:
test Match the characters “test” literally
\s Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
( Match the regular expression below and capture its match into backreference number 1
\d Match a single digit 0..9
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
You can find out more here
There's another way in powershell 7 with script blocks { }. You also need the subexpression operator $( ) to refer to object properties or arrays inside a string. I'm just saving $_ to $a so you can look at it. It's a little more convoluted, but sometimes the timing of '$1' (note the single quotes) isn't what you need, like if you want to add to it.
"this is a test 123 ... this is only a test" -replace "test\s+(\d+)",
{ $a = $_ ; "test $(1 + $_.groups[1].value)" } # 1 + 123
this is a test 124 ... this is only a test
$a
Groups : {0, 1}
Success : True
Name : 0
Captures : {0}
Index : 10
Length : 13
Value : test 123
ValueSpan :

Powershell loop that counts down

I'm trying to print a warning to let the user know that 0 isn't a valid option for an assignment for class. Just started learning about powershell and can't find any help on how to set a parameter like this.
Assignment is 3.) Write a loop that calculates $num^2 for each iteration and prints the value using Write-Host. This loop must execute at least once and beginning counting down. When $num = 0, the loop should end. Prevent this loop from receiving $num as 0 as this will cause an infinite loop. If 0 is set as $num, print a warning to let the user know that 0 isn’t a valid option.
So far this is what I have
$num=Read-Host -Prompt 'Enter a number'
do
{
write-host $num
$num--
}
until($num -eq -1)
Any help would be greatly appreciated
There are two fundamental problems:
Read-Host always returns a string, and --, the decrement operator, can only be used on numbers; you must convert the string to a number first:
[int] $num = Read-Host 'Enter a number'
write-host $num $num-- doesn't work as expected: while the $num references are expanded, the trailing -- is considered a string literal, not the decrement operator; to treat $num-- as an expression, you must enclose it in (...); also, to print the already decremented number, reverse the operands:
$num = 42; Write-Host ($num--) $num yields 42 41, as intended.
Incorrect: $num = 42; Write-Host $num $num-- yields 42 42--
The - complex - rules PowerShell uses when parsing unquoted command arguments are summarized in this answer
Try this:
$num = Read-Host -Prompt 'Enter a number'
$num = [int]::Parse( $num )
do
{
write-host "$num square is $([Math]::Pow($num,2))"
}
while(--$num)

How to compare user defined variable to string literal

I'm trying to write a script to allow users to input a filename and display either the number of lines, words, characters, or all three, that are in the file depending on whether the user enters 'l' (lines), 'w' (words), 'c' (characters), or 'a' (all).
Here's what I have so far:
#!/bin/sh
# Prompt for filename
read -p 'Enter the file name: ' filename
# Prompt which of lines, words, or chars to display
read -p 'Count lines, words, characters, or all three (l, w, c, a)? ' display
while [ $display -ne "l" -o $display -ne "w" -o $display -ne "c" -o $display -ne "a" ]
do
echo "Invalid option"
read -p 'Count lines, words, characters, or all three (l, w, c, a)? ' display
done
# Display to stdout number of lines, words, or chars
set `wc $filename`
if [ $display -eq "l" ]
then
echo "File '$4' contains $1 lines."
elif [ $display -eq "w" ]
then
echo "File '$4' contains $2 words."
elif [ $display -eq "c" ]
then
echo "File '$4' contains $3 characters."
else
echo "File '$4' contains $1 lines, $2 words, and $3 characters."
fi
If I run the script and supply a file called trial.txt and choose option w, I getting the output:
./icount: 11: [: Illegal number: w
./icount: 19: [: Illegal number: w
./icount: 22: [: Illegal number: w
./icount: 25: [: Illegal number: w
File 'trial.txt' contains 3 lines, 19 words, and 154 characters.
Can someone help me interpret this error?
I figured it out. -eq and -ne are integer comparison operators. You have to use = and != when comparing strings.
Also you should use AND conditions in while loop
#!/bin/sh
# Prompt for filename
read -p 'Enter the file name: ' filename
# Prompt which of lines, words, or chars to display
read -p 'Count lines, words, characters, or all three (l, w, c, a)? ' display
while [ "$display" != "l" -a "$display" != "w" -a "$display" != "c" -a "$display" != "a" ]
do
echo "Invalid option"
read -p 'Count lines, words, characters, or all three (l, w, c, a)? ' display
done
# Display to stdout number of lines, words, or chars
set `wc $filename`
if [ $display == "l" ]
then
echo "File '$4' contains $1 lines."
elif [ $display == "w" ]
then
echo "File '$4' contains $2 words."
elif [ $display == "c" ]
then
echo "File '$4' contains $3 characters."
else
echo "File '$4' contains $1 lines, $2 words, and $3 characters."
fi

Perl: Format table with curl outputs

I have something like the following curl code:
foreach my $value ('1', ..., '5') {
my $count = 1;
print "\nValue: $value\n\t";
my $start = `curl -m 10 -s "http://SITE/?value=$value" -c cookie.txt`;
my $end1 = `curl -m 10 -s "http://SITE2" -b cookie.txt`;
if($end1 ne "") {print ". "}; else print "$count ";
my $end2 = `curl -m 10 -s "http://SITE3" -b cookie.txt`;
if($end2 ne "") {print ". "}; else print "$count ";
my $end3 = `curl -m 10 -s "http://SITE4" -b cookie.txt`;
if($end3 ne "") {print ". "}; else print "$count ";
$count++;
}
So from value 1 to 5, it visits a website and stores the cookie value in cookie.txt. Then it visits 3 different websites using the stored cookies in cookie.txt. Once it visits these sites, it prints current count (or . if the request timed out after 10 seconds).
An example output for this would be:
Value: 1
1 1 1 2 . 2 3 3 3 4 . . . 5 5
Value: 2
. . 1 2 2 2 3 3 3 4 . 4 5 5 .
Would it be possible to format the output to look like:
Value: 1
Site2: 1 2 3 4 .
Site3: 1 . 3 . 5
Site4: 1 2 3 . 5
Value: 2
Site2: . 2 3 4 5
Site3: . 2 3 . 5
Site4: 1 2 3 4 .
The issue I have is that in the loop, I would only like to run $start once per loop. With the way I want it formatted, it would have to be run once per site (3 times).
Your requirement is a bit confusing, but this will give you the output you're seeking:
my #sites = qw( SITE2 SITE3 SITE4 );
foreach my $value ('1'..'5') {
print "\nValue: $value\n";
my $start = `curl -m 10 -s "http://SITE/?value=$value" -c cookie.txt`;
for my $site (#sites) {
print "\t$site ";
for (1..5) { # assuming you want to fetch each url 5x
my $end = `curl -m 10 -s "http://$site" -b cookie.txt`;
print $end eq '' ? '. ' : $_.' ';
}
print "\n";
}
}
Please turn on use strict; and use warnings.
If you did, you'd find:
foreach my $value ('1', ..., '5') {
print $value,"\n";
}
Is a syntax error. Which is not a good start. Perhaps you want:
foreach my $value ( 1..5) {
print $value,"\n";
}
Likewise you've to a $count variable that you never change, because you scope it locally within your loop (via my) and set it to 1 each iteration. And then increment it right at the end, just before it drifts out of scope.

How to Convert While/Case statements in bash to perl

Here is the loop in bash:
while [ $# -ge 1 ]; do
case $1 in
-a)
shift
NUM_AGENTS=$1
;;
-h)
shift
HOST_NAME=$1
;;
-t)
shift
TIME_STAGGER=$1
;;
-un)
shift
USER_NAME=$1
;;
-pw)
shift
USER_PASS=$1
;;
-p)
shift
TARGET_PAGE=$1
;;
-s)
shift
COMMON_SID=$1
;;
esac
shift
done
How can i convert this in perl so that the argument would populate the values in the command line
php loadAgent_curl.php $NUM_AGENTS $HOST_NAME $procStartTime $i $TARGET_PAGE $reqlogfile $resplogfile $USER_NAME $USER_PASS $execDelay $COMMON_SID &
------- appended to question:
this certainly helps, and i really appreciate it, is there any way to access these parameters outside the getOptions ? here is rest of the bash script: my $i="0";
my $startTime=date +%s;
startTime=$[$startTime+$NUM_AGENTS+10]
my $PWD=pwd;
my $logdir="\$PWD/load-logs";
system(mkdir $logdir/$startTime);
my $reqlogfile="$logdir/$startTime/req.log";
my $resplogfile="$logdir/$startTime/resp.log";
print "\n";
print "##################\n";
print "LAUNCHING REQUESTS\n";
print " HOST NAME : \$HOST_NAME\n ";
print " TARGET PAGE : \$TARGET_PAGE\n ";
print " # AGENTS : \$NUM_AGENTS\n ";
print " EXECUTION TIME : \$startTime (with random stagger between 0 and \$TIME_STAGGER seconds)\n ";
print " REQ LOG FILE : $reqlogfile\n ";
print " RESP LOG FILE : $resplogfile\n ";
print "##################\n";
print "\n";
#
#
highestStart=$startTime
$startTime += $ARGV[0] + 5;
my $dTime = localtime( $startTime );
print "\n##################\nLAUNCHING REQUESTS\n
COUNT: $ARGV[0]\n
DELAY: | 1 \n
The scripts will fire at : $dTime\n##################\n\n";
while ( $ARGV[0] > $i )
{
$i++;
system("php avtestTimed.php $ARGV[0] $ARGV[2] $startTime");
print "RUN system('php avtestTimed.php $ARGV[0] $ARGV[2] $startTime'); \n";
sleep 1;
}
#
#
while [ $NUM_AGENTS -gt "$i" ]
do
i=$[$i+1]
execDelay=$((RANDOM % $TIME_STAGGER))"."$((RANDOM % 100))
procStartTime=$[$startTime]
procStartTime=$[$startTime+$execDelay]
if [ $procStartTime -gt $highestStart ]
then
highestStart=$procStartTime
fi
echo "STATUS: Queueing request $i with a delay of $execDelay seconds"
echo " '--> COMMAND: php loadAgent_curl.php $NUM_AGENTS $HOST_NAME $procStartTime $i $TARGET_PAGE $reqlogfile $resplogfile $USER_NAME $USER_PASS $execDelay $COMMON_SID"
php loadAgent_curl.php $NUM_AGENTS $HOST_NAME $procStartTime $i $TARGET_PAGE $reqlogfile $resplogfile $USER_NAME $USER_PASS $execDelay $COMMON_SID &
sleep 1
done
echo "STATUS: Waiting for queued requests to be ready"
while [ date +%s -lt $startTime ]
do
sleep 1
done
#
echo "STATUS: Waiting for last request to issue"
while [ date +%s -lt $highestStart ]
do
sleep 1
done
#
echo "STATUS: Last response issued"
#
echo "STATUS: Waiting for response log file to be created"
while [ ! -e "$resplogfile" ]
do
sleep 1
done
#
while [ wc -l "$resplogfile"| awk '{print $1'} -lt $NUM_AGENTS ]
do
#echo "(wc -l "$resplogfile"| awk '{print $1'} of $NUM_AGENTS responses recorded)"
sleep 1
done
echo "STATUS: FINISHED"
while true; do
read -p "Do you wish to view the request log? [y/n]" yn
case $yn in
[Yy]* ) cat $reqlogfile; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
while true; do
read -p "Do you wish to view the response log? [y/n]" yn
case $yn in
[Yy]* ) cat $resplogfile; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
Getopt::Long library is a standard Perl way to process command line options.
Something like this will work. Not tested - caveat emptor!
Please note that since your PHP parameters are a mix between command line options AND some unidentified variables, I have designed the first example so that ALL the possible options should be stored in %args hash (e.g. your program should use $args{procStartTime} instead of $procStartTime). This allowed me to make it very short and generic.
If this is hard to read/understand, I also have a second example that's more straightforward but less generic
use Getopt::Long;
my #php_arg_order = qw(a h procStartTime i p reqlogfile
resplogfile un pw execDelay s);
my %args = map {$_ => ""} #php_arg_order;
$args{procStartTime} = "something";
$args{reqlogfile} = "a.log";
# More defaults for variables NOT passed in via command line.
# Populate them all in %args as above.
# Now load actual command line parameters.
GetOptions(\%args, map { "$_=s" } #php_arg_order) or die "Unknown parameter!\n";
system(join(" ",
"php", "loadAgent_curl.php",map { $args{$_} } #php_arg_order}, "&"));
A second, less advanced but more direct option is:
use Getopt::Long;
my %args = ();
# Now load actual command line parameters.
GetOptions(\%args,
"NUM_AGENTS|a=s"
,"HOST_NAME|h=s"
,"USER_NAME|un=s"
# ... the rest of options
# The "XXX|x" notaion allows using alias "-x" parameter
# but stores in $args{XXX} instead for better readability
) or die "Unknown parameter!\n";
system("php loadAgent_curl.php $args{NUM_AGENTS} $args{HOST_NAME} $procStartTime $i $args{TARGET_PAGE} $reqlogfile $resplogfile $args{USER_NAME} $args{USER_PASS} $execDelay $args{COMMON_SID} &");