Saturday, May 24, 2008

Check for presence in a line : Awk


Input File:


$ cat atnd.txt
AA,BB,CC,DD,EE
BB,CC,EE
AA,BB,DD
AA,CC,DD,EE


Check whether AA,BB,CC,DD,EE records are present in each line.
If present, put a (P), if not put a (A)

i.e. Required Output:


AA(P) BB(P) CC(P) DD(P) EE(P)
AA(A) BB(P) CC(P) DD(A) EE(P)
AA(P) BB(P) CC(A) DD(P) EE(A)
AA(P) BB(A) CC(P) DD(P) EE(P)


Awk solution:

$ awk 'BEGIN{FS=",";OFS=" "
n=split("AA,BB,CC,DD,EE",a,FS)}
{
for(i=1;i<=n;i++) {
s=match($0,a[i])?a[i]"(P) ":a[i]"(A) "
printf("%s",s)
}
print ""
}' atnd.txt

4 comments:

Sanjanaa Nagarajan said...

Hey This works great!!!..can u tell me how to get the count instead of P?

Jadu Saikia said...

@Sanjanaa Nagarajan, thanks for the query. Could you please put the expected output for this example, I would try that. Thanks.

Sanjanaa Nagarajan said...

For example:

AA,BB,CC,DD,EE,AA
BB,CC,EE,EE
AA,BB,DD,DD,DD
AA,CC,DD,EE

Required Output:


AA(2) BB(1) CC(1) DD(1) EE(1)
AA(A) BB(1) CC(1) DD(A) EE(2)
AA(1) BB(1) CC(A) DD(3) EE(A)
AA(1) BB(A) CC(1) DD(1) EE(1)

Karan Bohra said...


sed -e '
1{
x
s/.*/AA(A) BB(A) CC(A) DD(A) EE(A)/
x
}

/\n/!G
s/,/\n/

/^\(.*\)\n.*\n\(.*[ ]\)\{0,1\}\1(A)/{
s//&\n/
s/(A)\n/(P)/
}
/\n.*\n/D
/^\(.*\)\n\(.*[ ]\)\{0,1\}\1(A)/{
s//&\n/
s/(A)\n/(P)/
}

s/.*\n//

x
s/.*/AA(A) BB(A) CC(A) DD(A) EE(A)/
x
' < atnd.txt


perl -lpe '
my $l = $_;
$_ = join " ",
map { $l =~ /(?:^|,)$_(?:,|$)/ ? "$_(P)" : "$_(A)" }
qw/AA BB CC DD EE/;
' < atnd.txt


For the case of showing the match with numbers as reqd by OP S. Nagarajan:

perl -ple '
my $l = $_;
$_ = join $", map {
my $k =(()= $l =~ /(?:(?<=^)|(?<=,))$_(?=(?:,|$))/g) || "A";
"$_($k)";
} qw/AA BB CC DD EE/
' atnd.txt

© Jadu Saikia www.UNIXCL.com