-1

I have file like

123|3a|3b
747|3a|3b|3c|3d
636|3c|3b

Output :

123 -3c 3d
636 -3a 3d 

It should compare 3a,3b,3c,3d and show the missing one .

I tried using

awk '/3a/3b/3c/3d' file.txt

but not able to figure out how to compare single string.

Inian
  • 80,270
  • 14
  • 142
  • 161
  • 4
    What on earth did you think `awk '/3a/3b/3c/3d'` would do? – 123 Jul 18 '16 at 13:56
  • @ParthaNanda: Does the solution **have** to be in one of the languages you mention (awk, shell), or can it be also in another commonly available language (Perl, Ruby, Python)? In case of Shell, should it be a particular shell, or can it be any shell? Is the list of string to check restricted to the four terms 3a,...,3d, or does it need to be extendable (to enable one day a 2f, for instance)? – user1934428 Jul 18 '16 at 14:56
  • @user1934428 it has to be in shell as i dont have any other option .i tried to use perl in the environment , but some constraints are stopping me . – Husk01inJun Jul 19 '16 at 09:47

2 Answers2

0

This awk-solution should do the job

awk -F\| 'BEGIN{OFS=" "}{str=""
           str=sub("3a",$0) ? str : str"3a"
           str=sub("3b",$0) ? str : str"3b"
           str=sub("3c",$0) ? str : str"3c"
           str=sub("3d",$0) ? str : str"3d"
           if(str != ""){gsub(/[abdc]/,"& ",str)
           $0=$1" -"str
           print $0}}' test

Limitation: The first column must not contain "a", "b", "c", or "d".

Output:

123 -3c 3d 
636 -3a 3d 

More robust if the "-" is not required:

awk -F\| '{str=""
           str=sub("3a",$0) ? str : str"3a"
           str=sub("3b",$0) ? str : str"3b"
           str=sub("3c",$0) ? str : str"3c"
           str=sub("3d",$0) ? str : str"3d"
           if(str != ""){gsub("3"," 3",str)
                         print $1""str}}' test

Output:

123 3c 3d
636 3a 3d
F. Knorr
  • 3,045
  • 15
  • 22
  • Thanks Mate , its working , but now am trying to out the condition string in a config file so that in future it can be modified .For example 3A,3B,3C,3D will be there in a config file and my script will fetch it from there and compare with the above data . – Husk01inJun Jul 19 '16 at 09:55
  • `str=sub("3a",$0) ? str : str"3a"` means `replace 3a with the value of the whole of the current line if it was found in the current line and then set str....` which makes no sense. Maybe you meant `str=sub("3a","&") ? str : str"3a"` or `str=/3a/ ? str : str"3a"` or something? In any case, it'll fail if `13a` or similar can be present and the unparenthesized ternary expression could produce syntax errors on some awks. – Ed Morton Jul 24 '16 at 21:59
0
$ cat list
3a,3b,3c,3d
$
$ cat file
123|3a|3b
747|3a|3b|3c|3d
636|3c|3b
$
$ cat tst.awk
NR==FNR {
    for (i=1; i<=NF; i++) {
        reqd[++numReqd] = $i
    }
    next
}
{
    c=0
    for (i=1; i<= numReqd; i++) {
        if ( $0 !~ "[|]" reqd[i] "([|]|$)" ) {
            printf "%s%s%s%s", (++c>1?"":$1), OFS, (c>1?"":"-"), reqd[i]
        }
    }
    if (c) {
        print ""
    }
}
$
$ awk -f tst.awk FS=',' list FS='|' file
123 -3c 3d
636 -3a 3d
Ed Morton
  • 188,023
  • 17
  • 78
  • 185