## Friday, October 22, 2010

### Check equality of multiple numbers - awk

My input file 'file.txt' contains 4 values of a certain metric for each of the following 'Continents'.
`\$ cat file.txtContinent Val1 Val2 Val3 Val4AS 440518 440518 440516 440516AF 253317 253317 253315 253317EU 245397 245397 245397 245397OC 226410 226410 226410 226410NA 221961 221961 221962 221961`

Required : I was required to find out only those 'Continents' for which 'all' values are 'same'.

Solutions:

1) Using awk:
`\$ awk '    /^Continent/ {print \$1; next}    \$2==\$3 && \$3==\$4 && \$4==\$5 {print \$1}' file.txt`

Output:
`ContinentEUOC`

2) Wrote this python program using python 'sets' (Unordered collections of unique elements) to achieve the same. Something like:
`from sets import Setfor line in open("file.txt"):    if line.startswith('Continent'):        print line.split()[0]    firstfield = line.split()[0]    remaining = line.split()[1:]    vals = Set(remaining)    if len(vals) == 1:        print firstfield`

Executing it:
`\$ python printequal.pyContinentEUOC`

3) Any other solution using Bash, Awk or any other scripting languages ? Readers, please put your solutions here in the comment section. Much appreciated.

Related:
- Bash function to compare multiple numbers equality

Derek Evan Schrock said...

GNU AWK running in posix mode:

BEGIN { getline; if( \$1 ~ /^Continent/ ) { print \$1 } }
{ if( match( \$0, "^[A-Z]{2} ("\$2" ?)+\$" ) ) { print \$1 } }

Unknown said...

@Derek Evan Schrock, thanks for the solution:

when I tried this:

\$ gawk 'BEGIN { getline; if( \$1 ~ /^Continent/ ) { print \$1 } }
{ if( match( \$0, "^[A-Z]{2} ("\$2" ?)+\$" ) ) { print \$1 } }' file.txt

Only output following:
Continent

Unknown said...

grep -E '^[A-Z]+ ([0-9]+) /1 /1 /1' file.txt

Unknown said...

## Bash
unset flag
while IFS= read -r line; do
set -f; set -- \$line; \${flag+":"} echo "\$1"; flag=
unset allEQ
c=\$1; v=\$2; shift 2
for arg
do
case \$arg in "\$v") :;; *) allEQ=; break;; esac
done
\${allEQ+":"} echo "\$c"
done < file.txt

## Perl
perl -lane '
print \$F[0] if \$. == 1;
grep !/^\$F[1]\$/, @F[2..\$#F] or print \$F[0];
' < file.txt

## Sed
sed -ne '
1s/ .*//p
s/^\([A-Z][A-Z]\)\([ ][1-9][0-9]*\)\2\2*\$/\1/p
' < file.txt

## Dc
< file.txt perl -pale '
\$.==1 and \$_ = join(\$", map { "[\$_]" } @F),next;
\$a=0; \$_ = join \$", map { !\$a++ ? "[\$_]" : \$_ } @F;
' |
dc -e "
[q]sq
[pq]sa
[z1=a lN-0=b]sb
[?z0=q sNlbxc l?x]s?
?s0s0s0s0pc
l?x
"