test command in KornShell (ksh) - shell

I have a question on the test command in the KornShell (ksh). I know -ne is for comparing integers and != is for comparing strings. How will the test command behave if one argument is a string and the other is an integer? I have below conditions in my code and both are working properly.
Code:
myCount=1
myCount=`expr $myCount+ 0`
temp=`ps -aef | grep damn | wc -l`
if [ $temp -ne $myCount]; then
echo ERROR Number
fi
if [ $temp != $myCount ]; then
echo ERROR Strings
fi
Output:
ERROR Number
ERROR Strings

The type is not relevant because it's a simple text substitution. In other words, the value of the variable $temp will be substituted in place of $temp (for example).
At least for the version of ksh I'm running, for the numeric comparison, if the value starts with a non-numeric, it will equate to 0. If it starts with a numeric but contains non-numerics, you will get an error.
For example:
$ export s1=xyz
$ export s2=7xyz
$ export i1=0
$ if [ $i1 -eq $s1 ]
> then
> echo equal
> fi
equal
$ if [ $i1 -eq $s2 ]
> then
> echo equal
> fi
ksh: 7xyz: bad number `7xyz'
However, based on your comments, that may not be the case for all versions of ksh.
Based on that, I would try to ensure that you use string comparisons for strings and numeric comparisons for numbers. Anything else may be non-portable.

But your code is flawed anyway.
temp=ps -aef | grep damn | wc -l
will always return at least 1, since it will find the grep command as well as being a string padded with leading spaces, which is why both of your tests are true.
Piping to wc is also unnecessary since the -c switch of grep will count for you.
better code would be:
temp=ps -aef |grep damn |grep -cv grep
which will return the number of running instances of processes containing the damn string and it will be a number.

Using ksh93 and GNU coreutils expr 7.4 your command:
myCount=`expr $myCount+ 0`
gives me a syntax error and sets myCount to null which causes both if statements to output "ksh: [: argument expected" errors. Try putting a space before the plus sign. Also, there needs to be a space before ].
You shouldn't need to convert myCount or temp to integers. The coercion of myCount using expr is completely unnecessary.
I prefer this form for comparing integers since it allows you to use symbolic comparison operators such as != and > instead of -ne and -gt:
if (( $temp != $myCount ))

Related

script in bash two if condition and print in for loop

Hello im learning to script in bash, i trying to solve a little exercise.
The Exercise is this
If the variable named "basenew" contains the contents of the variable
named "valuebase". "basenew" must contain more than 113,469
characters. If both conditions are met, the script must then print
the last 20 characters of the variable "basenew".
My code is
#!/bin/bash
basenew="8dm7KsjU28B7v621Jls"
valuebase="ERmFRMVZ0U2paTlJYTkxDZz09Cg"
for i in {1..40}
do
basenew=$(echo $basenew | base64)
if [[ $basenew =~ $valuebase && ${#basenew} -ge 113469 ]] ; then
echo $i
echo $basenew | wc -c
StrLen=`echo ${basenew} | wc -c`
From=`expr $StrLen - 20`
echo $basenew | cut -c ${From}-${StrLen}
else
echo "error"
fi
done
But im stuck, because prints in the loop 28, and are the 20 last but isn't the correct answer.
Any advice to print the last 20 characters using tail -c 20?
Thanks
Why do you think the value of basenew will change during the execution of your loop? You never assign it. But you assign var that you never use, could it be the issue? Yes it is, you need to update basenew, not the unused var.
There is another problem with your script: cut applies your character selection on each line of the input. base64, by default, splits the output in lines of 76 characters. So, after a while, you have many short lines. And as they all are much shorter than your specification cut would only print a lot of newlines, not the last 20 characters of the string. You could change the behaviour of base64 with base64 -w0 but it would also change the results of each iteration and you would probably never match the reference string.
Instead of piping echo in cut follow joop's suggestion: "${basenew: -20: 20}" expands as the 20 last characters of the value of basenew. Or, a bit simpler but equivalent: "${basenew: -20}". Do not forget the space between : and -20, it is needed.
Finally, you could use more built-in bash constructs to avoid external commands (wc, echo, cut), use the modern $(...) instead of the old backticks, and use the arithmetic evaluation (((...))) instead of the obsolete expr. Try, maybe:
#!/usr/bin/env bash
# file: foo.sh
basenew="8dm7KsjU28B7v621Jls"
valuebase="ERmFRMVZ0U2paTlJYTkxDZz09Cg"
for i in {1..40}; do
basenew=$(echo "$basenew" | base64)
if [[ $basenew =~ $valuebase ]] && (( ${#basenew} >= 113469 )) ; then
printf '%d\n%d\n%s\n' "$i" "${#basenew}" "${basenew: -20}"
else
printf 'error\n'
fi
done
Demo:
$ ./foo.sh
error
...
error
28
113469
U2paTlJYTkxDZz09Cg==
error
...
error
Any advice to print the last 20 characters using tail
From the tail man-page:
-c, --bytes=[+]NUM
output the last NUM bytes; or use -c +NUM to output starting with
byte NUM of each file
Hence, if you have a variable x, you get the last 20 characters of it printed to stdout using
tail --bytes=20 <<<$x

I want stop the script if the subtraction is different to 0

I have a script to do research in my photo archive.
Beacause I've some files named with a merceological name before.
Since I want to avoid the problem that misspellings cause results to be lost. so I thought about this system.
Eg names files:
(Travel and Tourism) – titlea.jpg
(Travel and Tourism) – titleb.jpg
(Drinks) – titlea.jpg
I did this idea,
two researches, one precise with the exact name and the other extremely inaccurate with a few letters (consonants) that it is not possible for them to be missing (unless one does not type drunk). And that obviously are not all present together in other names.
If the subtraction is zero it means that the two results are the same and therefore without errors:
myfindTravelandTourism=$(find /PATH/ -type f -iname '*(Travel and Tourism)*' | wc -l)
StringVerifyTravelandTourism=$(find /PATH/ | cut -f1 -d '–' | grep
-i -F 'T' | grep -i -F 'R' | grep -i -F 'V' | wc -l)
if [ "${myfindTravelandTourism-StringVerifyTravelandTourism}" ≠ "0" ] ; then
echo "WARNING THE SCRIPT HAS DETECTED AN ORTOGRAPHICAL ERROR IN THE VIAGGI E TURISMO SECTOR!"
if [ {StringVerifyTravelandTourism} -ne ≠ "$0" ]; then
exit
fi
fi
But the error code bash:
[: ≠: integer expression expected.
I'm a beginner. This is my first conditional statement in bash
This ≠ is not an operator as a result it throws the error.
Also, to check for strings, you should use != instead of -ne. For example,
n1 -ne n2 To check whether numbers are algebraically equal or not.
s1 != s2 To check whether strings are not equal.
You can try the following code snippet:
if [[ $(( myfindTravelandTourism - StringVerifyTravelandTourism)) != 0 ]]; then
echo "not equal 0"
fi

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

grep -c in Bash doesn't recognize parameter

I have an output file, which looks something like this:
value1!value2#value3
value1!value2#value3
value1!value2#value3
I want to find out, with grep, how many times the value2 appears, so I'm doing this:
n = grep -c 'value2' outputfile.tmp
if[$n!=6] ; then
but when I run it, the console says this:
`"-c: command not found"`
like it doesn't recognize the parameter.
This should already choke on the assignment n = with a space: Bash parameter assignments can't have spaces. Secondly, to assign the output of a command to a parameter, you have to use command substitution:
n=$(grep -c 'value2' outputfile.tmp)
Notice that this will tell you how many lines contain at least one occurrence of value2, and not the actual number of value2. Consider:
$ grep -c 'value2' <<< 'value2value2'
1
If you know that there will only be one value2 per line (or you want to count lines), we're good. If you want to count occurrences, you have to use something like
n=$(grep -o 'value2' outputfile.tmp | wc -l)
grep -o prints each match on a separate line, and wc -l counts the lines.
Now, to check if the value of $n is unequal to six, you use a conditional. Unlike the assignments, this must have spaces.
The != comparison is for string comparison; for integers, you should use -ne ("not equal"):
if [ "$n" -ne 6 ]; then
Instead of the test command [ ], Bash has the more flexible [[ ]] conditional epxression:
if [[ "$n" -ne 6 ]]; then
where quoting isn't strictly necessary (but doesn't hurt!).
Or we can use an arithmetic expression:
if (( n != 6 )); then
where any parameter is evaluated without prepending $.
You need to enclose the command with $() to set it to a variable:
n=$(grep -c 'value2' outputfile.tmp)
This is a type of command substitution, see near the bottom of this page: http://www.tldp.org/LDP/abs/html/commandsub.html

Why does my script report ls: not found

I have the following korn script:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l > 1]]
then
exit "asdf"
fi
When I attempt to run it I get:
/hp/qa02/App/IPHSLDI/Data
./iftest.ksh: line 7: [[ls: not found
Why isn't my if statement working?
I'm trying to see if there are multiple checksum files in the Data directory. If there are I want to exit the script.
There are several problems:
There shouldn't be any spaces around = in the assignment.
You need spaces around [[ and ]] in the if statement.
To substitute the result of a command into the test expression, you need to use backticks or $(...).
The parameter to exit should be a number, I think you just want to echo the string.
> performs string comparison, you have to use -gt to perform numeric comparison.
So the full script should be:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ $(ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l) -gt 1 ]]
then
echo "asdf"
fi

Resources