LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   error comparing strings (https://www.linuxquestions.org/questions/programming-9/error-comparing-strings-4175666045/)

pedropt 12-16-2019 06:40 AM

error comparing strings
 
I am building a script to manually update my dovecot packages directly from dovecot repo , however this script does not do that job straight ahead .
First checks apt policy to see witch packages of dovecot are installed in system , and then write those packages names to a file .

I am posting here this part only of the code , but when i look into the logfile from apt and compare strings with IF statement i get "invalid arithmetic operator on my loop."

Code:

#!/bin/bash
basedir="/dovecot"
if [[ ! -d "$basedir" ]]
then
mkdir "$basedir"
mkdir "$basedir/update"
else
rm -f "$basedir/update/*.*"
rm "$basedir/dovelist"
rm "$basedir/filelist"
rm "$basedir/dovelist"
fi
echo "Checking dovecot installed packages"
apt-cache policy dovecot-* > aptinst

# get the line numbers where dovecot- exists
grep -n "dovecot-" aptinst | sed 's/\:/ /' | awk '{print$1}' > lines
a1=$(wc -l lines | awk '{print$1}')
for i in $(seq "$a1")
do

# read i line from lines file"
ln=$(sed -n ${i}p lines)

# add +1 to that line number (this will get Installed line)
ln=$((ln+1))

# On installed line bings up variable 2
rdinst=$(sed -n ${ln}p aptinst | awk '{print$2}' | sed 's/^.*://')
rjct="(none)"
echo "reading line $ln with output $rdinst"

# here checks if variable 2 is not equal to (none)
# (none) means package not installed
# in case some particular package is installed then a #version number will appear on variable2

if [[ "$rdinst" -ne "$rjct" ]]
then
if [[ ! -f "$basedir/installed" ]]
then
namepkg=$(sed -n ${i}p aptinst)
echo "Installed $namepkg  with version $rdinst" > installed
else
namepkg=$(sed -n ${i}p aptinst)
echo "Installed $namepkg  with version $rdinst" >> installed
fi
fi
done

exit 0

Eventually the problem is in the if statement , i changed the -ne with != and i did not get accurate output

rtmistler 12-16-2019 07:18 AM

If you mean this line:
Code:

if [[ "$rdinst" -ne "$rjct" ]]
My understanding is that you're not supposed to quote the variables, just strings themselves.

And it would be !=

Turbocapitalist 12-16-2019 07:24 AM

The != is the correct operator to compare strings. You might use "set -x" or "set -xv" earlier in the script and watch what it tells you about the process.

Some random comments. Making a directory and subdirectory can be done in a single move:

Code:

mkdir -p "$basedir/update"
grep, sed, and awk need never be combined:

Code:

. . .
awk '/dovecot-/ {sub(":"," "); print $1;}' aptinst > lines
. . .
rdinst=$(awk -v ln=${ln} '$0~ln {sub(/^.*:/,"",$2); print $2;}' aptinst)
. . .


BW-userx 12-16-2019 07:33 AM

Code:

if [[ ! -d "$basedir" ]]
then
mkdir "$basedir"
mkdir "$basedir/update"
else
rm -f "$basedir/update/*.*"
rm "$basedir/dovelist"
rm "$basedir/filelist"
rm "$basedir/dovelist"
fi

can be changed to
Code:

if [[ ! -d "$basedir" ]]
then
    mkdir -p "$basedir/update"
else
    rm -rf "$basedir/*
fi

leaving the $basedir there and everything within it deleted. remove the * if you want to delete that dir too.

this here
Code:

if [[ "$rdinst" -ne "$rjct" ]]
just checks the file names against each other, so they will never match if not named the same, you got a look inside of them.
example
Code:

#!/usr/bin/env bash

##check contents first line to see if match
f1=$HOME/test/ckfile1
f2=$HOME/test/ckfile2

if [[ $(cat $f1 | head -n1) == $(cat $f2 | head -n1) ]] ; then
  echo "match"
else
  echo "no match"
fi

MOD:
as @Turbocapitalist posted ahead of me, that awk he is doing is prob best to get what info out of the file that is needed to be checked against.

boughtonp 12-16-2019 07:39 AM

Quote:

Originally Posted by BW-userx (Post 6068386)
Code:

if [[ $(cat $f1 | head -n1) == $(cat $f2 | head -n1) ]] ; then

Why is the cat there? Wont that read the whole file then truncate, instead of just using head to read the first line?

Code:

head -n1 "$f1"

BW-userx 12-16-2019 07:44 AM

Quote:

Originally Posted by boughtonp (Post 6068388)
Why is the cat there? Wont that read the whole file then truncate, instead of just using head to read the first line?

Code:

head -n1 "$f1"

thanks, I never really used head to know how to input to it so I just defaulted to cat first then head it.

Code:

#!/usr/bin/env bash

##check contents first line to see if match
f1=$HOME/test/ckfile1
f2=$HOME/test/ckfile2

if [[ $(head -n1 $f1) == $(head -n1 $f2) ]] ; then
  echo "match"
else
  echo "no match"
fi

thanks for correcting me.

boughtonp 12-16-2019 07:54 AM

Also, regarding the mkdir/rm stuff... since -f and -p suppress errors regarding (non-)existence I think the whole if/else might not be needed.

Depending on the specifics of what should/shouldn't be deleted, perhaps one of these is suitable:
Code:

mkdir -p "$basedir/update"
rm -f "$basedir/update/*.*" "$basedir/dovelist" "$basedir/filelist"

Code:

[[ -d "$basedir" ]] && rm -rf "$basedir/*"
mkdir -p "$basedir/update"


pan64 12-16-2019 07:55 AM

Just a comment:
Code:

IFS= read -r line1 <file1
IFS= read -r line2 <file2
[[ $line1 == $line2 ]] && echo matches

is much more efficient I think, but not really important.

BW-userx 12-16-2019 07:57 AM

keeping in mind you need to add the -r (for recursive) if going past parent dir.
Code:

userx@FreeBSD12.1.org:~
$ mkdir -p go/go/go
 
$ rm -f go/*
rm: go/go: is a directory
 
$ rm -rf go/*


boughtonp 12-16-2019 08:02 AM

Quote:

Originally Posted by BW-userx (Post 6068398)
keeping in mind you need to add the -r if going past parent dir.

Yep, my edit came just too slow...


Quote:

Originally Posted by pan64 (Post 6068397)
[example] is much more efficient I think, but not really important.

It's useful to know, but my recommendation is readability first, unless/until efficiency becomes a measurable issue.

pedropt 12-16-2019 08:45 AM

Thanks for all the replies .

thanks for some tips .

I am not comparing files , what i am doing is to see in "Installed" field , pick whats next "var2" , and if output is different than "(none)" then pick up the name of that installed package only to a file .

example :

when loop gets to dovecot-pigeonhole-dbg:
it reads the next line "Installed" , then grabs "2:2.3.9.2-1+debian10" and compare with "(none)" .
In case it is different then writes "dovecot-pigeonhole-dbg:" to a file .
I am pretty sure there is a simple way to do this , and i have faith that someone here already figured out to do it in a single line ;) .

Quote:

dovecot-abi-2.2.abiv27:
Installed: (none)
Candidate: (none)
Version table:
dovecot-abi-2.2.abiv33:
Installed: (none)
Candidate: (none)
Version table:
dovecot-pigeonhole-dbg:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status

boughtonp 12-16-2019 09:14 AM

Quote:

Originally Posted by pedropt (Post 6068411)
I am not comparing files , what i am doing is to see in "Installed" field , pick whats next "var2" , and if output is different than "(none)" then pick up the name of that installed package only to a file .

Ah - this is why it's a good idea to explain what you're trying to achieve before explaining what you're stuck on, because you're right - this can be done in one line:

Code:

grep -Poz '(?<=\n|\A)dovecot.*:(?=\nInstalled: (?!\(none\)\n))' packages.txt
packages.txt contains the quoted text in your post.

Uses -P for Perl regex to get lookahead support, with -z to match across lines, and -o to only output the matched text.

The "(?<=\n|\A)" is start of line/content - it would ideally just be "^" but that's not supported with the -z flag.

The "dovecot.*" searches for all dovecot prefixed packages - if you need specific ones, replace it with "(package1|package2)"

The next bit looks for "\nInstalled: " that isn't followed by "(none)\n" - using a lookahead to not include it in the output.

This version does include the colon in the output, but if you don't actually want that, move the : inside the lookahead (i.e. just before the \n )

Assumes the "Installed:" line always directly follows the package name, which seems a safe assumption? If not, (and depending on exact format possibilities), I might filter the content first to remove other lines.

pedropt 12-16-2019 09:33 AM

Quote:

The "dovecot.*" searches for all dovecot prefixed packages - if you need specific ones, replace it with "(package1|package2)"
Here it is the problem , i want the script to check witch ones are installed without having to specify any of them .

In this file (aptinst), how to see witch packages are installed automatically without adding anything specifically to the script ?

Quote:

dovecot-submission:
Installed: (none)
Candidate: (none)
Version table:
dovecot-lmtpd:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-mysql:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-dbg:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-dev:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-gssapi:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-abi-2.3.abiv4:
Installed: (none)
Candidate: (none)
Version table:
dovecot-abi-2.3.abiv9:
Installed: (none)
Candidate: (none)
Version table:
dovecot-imapd:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-sieve:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-sqlite:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-pop3d:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-lucene:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-core:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-managesieved:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-common:
Installed: (none)
Candidate: (none)
Version table:
dovecot-ldap:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-auth-lua:
Installed: (none)
Candidate: 1:2.3.4.1-5+deb10u1~bpo9+1
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
dovecot-pgsql:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-abi-2.2.abiv27:
Installed: (none)
Candidate: (none)
Version table:
dovecot-abi-2.2.abiv33:
Installed: (none)
Candidate: (none)
Version table:
dovecot-pigeonhole-dbg:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
dovecot-submissiond:
Installed: 2:2.3.9.2-1+debian10
Candidate: 2:2.3.9.2-1+debian10
Version table:
*** 2:2.3.9.2-1+debian10 100
100 /var/lib/dpkg/status
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
dovecot-solr:
Installed: (none)
Candidate: 1:2.2.27-3+deb9u5
Version table:
1:2.3.4.1-5+deb10u1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages
1:2.2.27-3+deb9u5 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
500 http://auto.mirror.devuan.org/merged ascii-security/main amd64 Packages
dovecot-antispam:
Installed: (none)
Candidate: 2.0+20170109-1
Version table:
2.0+20170109-1 500
500 http://auto.mirror.devuan.org/merged ascii/main amd64 Packages
2.0+20170109-1~bpo9+1 100
100 http://auto.mirror.devuan.org/merged ascii-backports/main amd64 Packages


For this specific file i need this outputs :
Quote:

dovecot-lmtpd:
dovecot-imapd:
dovecot-sieve:
dovecot-pop3d:
dovecot-core:
dovecot-managesieved:
dovecot-ldap:
dovecot-pgsql:
dovecot-pigeonhole-dbg:
dovecot-submissiond:
But these outputs may change from system to system depending on witch packages a sys admin may have installed .
This is why i cant specify a specific package to grep .
And this is why i need to look into each package "Installed" field to see if have "(none)" or is different .

boughtonp 12-16-2019 10:29 AM

Quote:

Originally Posted by pedropt (Post 6068421)
i want the script to check witch ones are installed without having to specify any of them .

The command as given will do that - I copied your latest example into the file and here's the output:
Code:

$ grep -Poz '(?<=\n|\A)dovecot.*:(?=\nInstalled: (?!\(none\)\n))' packages.txt
dovecot-lmtpd:
dovecot-imapd:
dovecot-sieve:
dovecot-pop3d:
dovecot-core:
dovecot-managesieved:
dovecot-ldap:
dovecot-pgsql:
dovecot-pigeonhole-dbg:
dovecot-submissiond:

That looks like the same ten entries as your expected output.

You can even remove "dovecot" (leaving just the ".*" part) and it will continue to work even with package names not starting with dovecot (that might not be required, just pointing out the potential).

pedropt 12-16-2019 11:42 AM

dont know why but it is not working here .
what is your grep version ?
mine is 3.3 .
I have no idea if this is a grep version , but it is strange .


All times are GMT -5. The time now is 01:44 AM.