If Statement bash command - bash

I am having a problem with this code:
highmem="58.0"
counter=1
while [ $counter = 1 ];
do
#sleep 5
mem=`ps -C ats -o pid=,%mem= | awk {'print $2'}`
echo $mem
echo $highmem
if [ "$mem" -gt "$highmem" ]
then
echo test
fi
done
Getting ./memtest: line 9: [: 20.3: integer expression expected.
I can't figure it out what I'm doing wrong. I assume I'm comparing integer to text?

There are a couple things wrong with this code:
As Cyrus noted, you are missing a done at the end of the script, to end the loop.
[ $counter = 1 ] is not a valid comparison, you should use [ $counter -eq 1 ]
This loop will never end since the value of counter is never changed.
Apparently the values of mem and highmem are not both integers. Which you should notice from the print statements. Since both variables seem to be floats with a single digit after the period, simply multiply them by 10 and then compare them. This can be achieved as follows: if [ "${mem//./}" -gt "${highmem//./}" ].

The problem was two fold - first I was using -GT rather than > sign. The other problem was that I was comparing 11.6 to 60 .. So I was comparing text to numeric.
The simple work around was to round up or just remove the point or fraction out of the equation and then just do the work. There are may ways of doing thsi I just did it with awk and cut. So at the end my highmem was equal a whole number with no fraction as well as the mem so both number were turned to whole to compare
Thanks for all your helps

Related

How can i fix the bad substitution?

I got loc_list0,1,2,3,
and i try to do it efficiently and type
b=0
while [ $b -lt 4 ]
do
grep -c "${loc_list$b[0]}" Record$b.txt
done
It says Bad Substitution on ${loc_list$b[0]}, but ok for Record$b. What is the reason behind? I am new to bash shell can anyone tell me how to fix it instead of writing duplicate codes.
Thanks man!
But another problems come when i want to use two varibales for iteration
thanks man, how about i got two variables
b and c which works as counting numbers of iteration
such that:
b=0
c=0
while [ $b -lt 5 ]
do
temp_length=( "${loc_list$b[#]}" )
while [ $c -lt ${#temp_length[#]} ]
do
...
c=$((c+1))
done
...
b=$((b+1))
done
how to fix the bad substitution this time?
You need to use indirect parameter substitution. With arrays, the index you want is considered part of the name.
name=loc_list$b[0]
grep -c "${!name}" Record$b.txt
Record$b.txt works because it is a simple string concatenation, Record + $b + .txt. You aren't try to further expand the result.

Compare Decimals in Bash while Loop

In the below code, ShellCheck throws an error in the while clause.
count=10.0
while [ $count -le 20.0 ]
do
echo "Hello"
count=$(bc<<< "scale=4; (count+0.1)")
done
ShellCheck says:
Decimals not supported, either use integers or bc
I am not quite sure how to use bc in a while loop.
while [ $(bc <<< "scale=4; (count -le 20.0)" ]
How do I compare decimal numbers in a while clause? Any advice?
Bash doesn't support floating point arithmetic.
You can either use bc:
count="10.0"
limit="12.0"
increment="0.1"
while [ "$(bc <<< "$count < $limit")" == "1" ]; do
echo "Hello"
count=$(bc <<< "$count+$increment")
done
or awk:
while awk 'BEGIN { if ('$count'>='$limit') {exit 1}}'; do
echo "Hello"
count=$(bc <<< "$count+$increment")
done
I just wonder: why not (directly) count from 10.0 to 12.0 ?
for i in $(seq 10.0 0.1 12.0); do
echo "Hello"
done
Bash doesn't support floating pointing arithmetic. You can use bc for that comparison too:
count=10.0
while : ;
do
out=$(bc -l<<< "$count<20.0")
[[ $out == 0 ]] && { echo "Reached limit" ; exit 0; }
echo "Hello"
count=$(bc<<< "scale=4; ($count+0.1)")
done
Note that I added the missing $ to count inside the loop where you update count.
While bash doesn't handle floating point numbers, the seq utility does. [Note 1]
The basic syntax is seq FIRST INCREMENT LAST, so in your case you could use
for count in "$(seq 10.0 0.1 20.0)"; do
# something with $count
done
If you provide two arguments, they are assumed to be FIRST and LAST, with INCREMENT being 1. If you provide only one argument, it is assumed to be LAST, with both FIRST and INCREMENT being 1. As in your example, the sequence is inclusive so both FIRST and LAST will be produced provided that INCREMENT evenly divides FIRST−LAST.
You can also include an explicit format:
$ seq -f "%06.3f" 1 .5 2
01.000
01.500
02.000
One downside of this technique is that it precomputes the entire collection of values. If the loop will execute hundreds of thousands of times, that might use up a lot of memory, in which case you could use a pipe or process substitution instead:
while read count; do
# something with count
done < <(seq 10.0 0.000001 20.0)
Notes
seq is not Posix but it is almost always present; it's part of GNU coreutils and a similar utility, available in Mac OS X) has been in NetBSD since 3.0 and FreeBSD since 9.0.

Unix - Count line inside two files and sum the value

I want to count how much line within 2 files. I create function to get the value for each file, and sum it.
Here is the code :
count_sus_pop()
{
wc -l < ${SCRIPTDIR}/output/${OUTPUTFILE1}_${DATE}.csv
}
count_waive_pop()
{
wc -l < ${SCRIPTDIR}/output/${OUTPUTFILE2}_${DATE}.csv
}
if [$(count_sus_pop)+$(count_waive_pop) -gt 2];
then
pop="[POPULATION]"
else
pop=""
fi
If the summation result greater than 2, assign "[POPULATION]" to variable pop, else pop is empty.
My code doesn't work. Please give me your suggestion
My suggestion is to just use:
total_lines=$(cat "${SCRIPTDIR}/output/${OUTPUTFILE1}_${DATE}.csv" "${SCRIPTDIR}/output/${OUTPUTFILE2}_${DATE}.csv" | wc -l)
if [[ $total_lines -gt 2 ]]; then
pop="[POPULATION]"
else
pop=""
fi
You have some basic syntax errors in your script - I would suggest using ShellCheck to fix those.
In terms of counting the combined number of lines, I would suggest this approach:
total_lines=$(cat "${SCRIPTDIR}/output/${OUTPUTFILE1}_${DATE}.csv" "${SCRIPTDIR}/output/${OUTPUTFILE2}_${DATE}.csv" | wc -l)
That is, use cat to combine the two files and use wc -l to obtain the total number of lines.
Your test would then be if [ "$total_lines" -gt 2 ] - note that the spaces are important.
you need spaces around [ and ]. And the test operator doesn't perform arithmetic, so you need to use the shell arithmetic operator $(( ))
if [ $(( $(count_sus_pop)+$(count_waive_pop) )) -gt 2 ]
or you can use bash's built-in `[[ ]]`` operator:
if [[ $(count_sus_pop)+$(count_waive_pop) -gt 2 ]];

filtering files by number in bash error unary operator expected

I have a script that will find the distances between two atoms in pdb.
bash does not recognize decimals so I have put printf script to round the decimals.
and echo $b works fine and gives me a integer value.
but the if line for my filtering system does not work.
I get and error stating
[: -ge: unary operator expected
below is part of the script that I am working on.
a=$(awk '$2=='91'{x1=$6;y1=$7;z1=$8} $2=='180' {x2=$6;y2=$7;z2=$8} END{print sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2))}' ${names}.pdb.$i)
b= printf %.0f $a
echo $b
if [ $b -ge 1 ] &&[ $b -le 9 ]; then
any help will be greatly appreciated. Thank you in advanced.
b= printf %.0f $a
This line sets the value of b to nothing for the duration of the printf command, which sends its output to stdout
echo $b
This prints a blank line.
You must not put whitespace around the = in an assignment, and to store the output of a command into a variable, you use this syntax:
b=$( printf %.0f $a )
You're getting the error because $b is empty, and this is what bash sees:
if [ -ge 1 ] &&[ -le 9 ]; then
-ge is expecting operands on both the left and the right, and it doesn't see one.
With bash, you should (almost) always prefer [[ ... ]] over [ ... ] -- the double bracket form is not fooled by variables containing empty strings.
You should always quote your "$variables" -- unless you know exactly when to not quote them.

solaris simple bash script

I'm trying to execute this simple script in solaris.
I want to sort(numeric) the filenames of the files in source directory and copy the file one by one to another directory. And, I want to print a message after copying every 100 files.
#!/bin/bash
count=0
for i in `ls | sort -n`
do
cp $i ../target
count = $((count+1))
if[ $count%100 -eq 0 ]
then
echo $count files copied
sleep 1
fi
done
this is not working. I tried different things after searching in net.
I get errors like these -
syntax error at line 8: '(' unexpected.
syntax error at line 10: 'then' unexpected.
syntax error at line 13: 'fi' unexpected etc.
What is the problem with this script?
bash version - GNU bash, version 3.00.16(1)-release (sparc-sun-solaris2.10)
The basic problem with the script is spacing. You have spaces where you shouldn't have them:
(wrong) count = $((count+1))
(right) count=$((count+1))
(better) ((count++))
and you're missing spaces where you need them:
(wrong) if[ $count%100 -eq 0 ]
(right) if [ $((count % 100)) -eq 0 ]
(better) if ((count % 100 == 0))
count = $((count+1)) tries to run the command count passing it two arguments, = and the value of count+1. if[ ... tries to run the command if[ because [ is a valid word character; it doesn't automatically start a new token.
Having said all that, I'm puzzled by the unexpected ( error message. Could your bash be too old to recognize $(( syntax? Possibly. It's a very old bash.
count=$((count+1))
if [ `echo $count % 100 | bc` -eq 0 ]
Make these corrections.
Edit: Please try
count=`expr $count + 1`
I see a few errors here. First, you need double quotes around $i in case they have special characters.
Second, you shouldn't ever use
for i in `ls | sort -n`
Instead, try the following
ls -1 | sort -n | while read i
Third, change your if statement to
if ((count%5 == 0))
The (( syntax is bash is made just for integer math.
Fourth, change your counter increment to
((count++))
This is more concise. Also, the space in your version may break things. Remember, spaces matter.

Resources