Unix - Count line inside two files and sum the value - bash

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 ]];

Related

How to convert shell script variable from string to an integer

My script has a line that measures the number of instances of a process being run
procs=$(pgrep -f luminati | wc -l);
However, even though the content of $procs is a numeral, the shell script is not storing $procs as an integer. It is being stored as a string.
Therefore I cannot run conditionals like
if $procs > 3
Is there any way to convert this variable to integer type?
In bash > is truncate which writes to a file. You probably have a file called 3 now. You should use the comparitor -gt:
if [[ "$procs" -gt 3 ]]; then
...
fi
Also, you don't have separate types for integers and strings.
Edit:
As #chepner explained, for POSIX compatibility you should use single brackets:
if [ "$procs" -gt 3 ];
Should be
if [[ "$procs" -gt 3 ]]
then
...
fi

Bash: how do I convert a command with a number result then compare it with an operator

I am trying to execute a word count command on a log file and if the file has the "error" string, I want to take some action, but I can't seem to properly convert the grep to word count command to a real number so it compares properly to the greater than zero. So far with several variations, the conditional statement is always true.
if ((grep -Ei "error" myfile.log | wc -l)) > 0; then echo 1; else echo 0; fi
First of all, you can write conditions based on the exit code of programs.
If grep finds a matching line, it exits with success:
if grep -qEi "error" myfile.log; then echo 1; else echo 0; fi
I added the -q flag to not print the matching line, as you probably don't need it.
I strongly recommend to use the above solution, without wc.
But for the sake of completeness, here's some more explanation about different ways of comparing numbers.
One way to compare numbers is with -gt ("greater than") within [ ... ]:
if [ $(grep -Ei "error" myfile.log | wc -l) -gt 0 ]; then echo 1; else echo 0; fi
You can read about other operators within [ ... ] in help test.
Or using arithmetic context within ((...)):
if (($(grep -Ei "error" myfile.log | wc -l) > 0)); then echo 1; else echo 0; fi
Notice that in both of these examples I wrapped the grep ... | wc -l within a $(...) sub-shell to capture the output.
The syntax you wrote is incorrect.

Illegal number in shell script

I am new to writing scripts and am trying to start out with a simple one. I am stumped as to why I am receiving the error: [: 13: Illegal number: count from the code below. Line 13 is the last fi.
count=grep "^$(date -d -30minute +'%Y-%m-%d %H:%M')" /var/log/****/zlsapp.log | wc -l
if [ count -ge 50 ]
then
if [ count -lt 100 ]
then
exit 1
fi
if [ count -ge 100 ]
then
exit 2
fi
exit 0
fi
Also is there anyway to do compound if statements like if(count >= 50 && count < 100)?
Two reasons. (1) in bash variables are untyped (could be int, could be char). In order to remove ambiguity, you can specify the type with:
declare -i count
To tell bash it should be an int. (2) you need to dereference your variables with $ to get the number back. I.E.
[ $count -lt 100 ]
(it is also good practice to quote your variables - not required, but good practice: [ "$count" -lt 100 ]. Drop a comment if you still have trouble.
The line:
count=grep "^$(date -d -30minute +'%Y-%m-%d %H:%M')" /var/log/zumigo/zlsapp.log | wc -l
probably does not do what you think it does (or you've not accurately copied and pasted your actual code into the question). If run in the middle of 2014-08-01, it runs the command "2014-08-01 12:00" with the log file as an argument and the environment variable count set to the value grep, and pipes the output from the probably non-existent command to wc -l.
When you subsequently go to test $count in the test statements, it is an empty string, which doesn't convert properly to a number.
You probably meant:
count=$(grep "^$(date -d -30minute +'%Y-%m-%d %H:%M')" /var/log/zumigo/zlsapp.log | wc -l)
This captures the output of running grep on the log file and piping the output to wc -l.
If you run your script with bash -x or equivalent (the -x option usually shows the execution of the script), you should see this.
The problem is that count does not refer to the variable count; it's simply the string "count".
Change:
if [ count -ge 50 ]
to
if [ $count -ge 50 ]
and make the corresponding change elsewhere (but not in the initial assignment).
You should also use double quotes:
if [ "$count" -ge 50 ]
Also is there anyway to do compound if statements like if(count >= 50 && count < 100)?
Yes:
if [ "$count" -ge 50 -a "$count" -lt 100 ]
is likely to work, but the -a (logical and) operator is marked as obsolescent by POSIX. Instead write
if [ "$count" -ge 50 ] && [ "$count" -lt 100 ]
If you're using bash, info bash and search for the "test" command ([ is an alias for test).
And if you're using bash, you should consider using [[ ... ]] rather than [ ... ] -- or you can use (( ... )) for arithmetic expressions. See the bash documentation for more information (follow the iink or type info bash).
In addition to the missing $ signs, the first line of your script:
count=grep "^$(date -d -30minute +'%Y-%m-%d %H:%M')" /var/log/****/zlsapp.log | wc -l
doesn't set the count variable, since you're not capturing the output of the grep ... | wc -l command. To do so:
count=$(grep "^$(date -d -30minute +'%Y-%m-%d %H:%M')" /var/log/****/zlsapp.log | wc -l)
(Yes, $(...) can be nested.)

Subtracting two float variables and comparing shell script

I have two floating-point variables, time and prev_time, and I need to subtract them, and check if less than 0. I've looked up in dozens of forums, but can't seem to find an answer that works. I need to do something similar to:
if [[ `expr $time-$prev_time | bc` -lt 0 ]]
Any help is appreciated
From your use of [[ ... ]], I'll assume you are using bash. If you only care that the difference is less than 0, you only care that $time is less than $prev_time. You can split the floating point values into its integer parts, then compare them separately:
IFS=. read time_int time_frac <<< $time
IFS=. read prev_in prev_frac <<< $prev_time
if (( time_int < prev_int || (time_int == prev_int && time_frac < prev_frac) )); then
Or, you can use bc this way (plus, it's POSIX compliant):
if [ "$( echo "$time - $prev_time < 0" | bc )" = 1 ];
bc outputs 1 if the comparison is true, 0 if false.

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