0

I was able to extract numbers (ids) between pattern(Available for user: and Chosen by user:)and match if a particular user chose an id from what was available to him from list of ids

Available for user:75=1654 at Time=5504.09 
Chosen by user:75=1655

Available for user:10=1300 at Time=550.09
Available for user:10=1301 at Time=550.09
Available for user:10=1303 at Time=550.09
Chosen by user:10=1301

I used sed pattern given in reply to my question at compare available list with chosen ids in shell script

The sed pattern used was this

 /^Avail/{
    s/[^=]*=([^ ]*).*/\1/;H
}
/^Chosen/{
    s/.*=//;G;h;x;y/\n/,/
    s/,/ is ab in /;s/$/,/
    /(.*) is.*,\1,/s/ab/pre/
    s/(ab|pre) in ,(.*),/\1sent in \2/
    p;s/.*//;x
}

Now i have a file with globalID and localID added after line "Chosen by user:" i.e.

Available for user:75=1654 at Time=5504.09 
Chosen by user:75=1655
globalID=1000 localID=1655

Available for user:10=1300 at Time=550.09
Available for user:10=1301 at Time=550.09
Available for user:10=1303 at Time=550.09
Chosen by user:10=1301
globalID=1020 localID=1301 

Available for user:20=1400 at Time=550.09
Available for user:20=1501 at Time=550.09
Available for user:20=1503 at Time=550.09
Chosen by user:20=1503
globalID=1030 localID=1503

Now i want print globalID in each line for each match and no match in two seperate files, file1 and file2 .The output for file1 (match case) where globalID of an id selected from available list by particular user is stored as:

1020
1030

The output for file2 (no match case) where globalID of an id not selected from available list by particular user is stored as:

1000

I tried

sed -nrf script.sed input.txt  | grep absent -A1 > file2

and

sed -nrf script.sed input.txt | grep present -A1 > file1

but it does not give next line of source file instead it gives next line of sed script output.

4
  • 1
    Add the expected output to your question. Jul 23, 2020 at 19:25
  • @NasirRiley I have shown output for file1 as 1020 1030 and for file2 as 1000 Jul 24, 2020 at 3:06
  • That would be absolutely trivial in awk. You had a clear, simple, robust, portable awk answer with multiple upvotes in your previous question but went with a convoluted, fragile, non-portable sed expression with no upvotes and which didn't even produce your expected output instead. I can't imagine what made you make that decision but hopefully the difficulty you're now facing trying to enhance it for this minor requirements change will make you reconsider.
    – Ed Morton
    Jul 25, 2020 at 15:35
  • I see for your last question you had clear, simple, portable awk answers too but went with a solution that requires a pipeline of 3 commands, one of which is GNU-only grep using their experimental -P option to use PCREs which aren't supported in any standard UNIX tool. Grep is best for doing g/re/p, sed is best for doing s/old/new/, for any text processing that's more than that you should really consider just using awk - it's a tiny, simple language used by a very powerful text processing tool that is standard on all UNIX boxes.
    – Ed Morton
    Jul 25, 2020 at 15:49

1 Answer 1

0

If we take the awk answer I posted to your previous question and tweak it to print the information when it hits an empty line or the end of file instead of when it hits the "Chosen" line (which I should have done in the first place but I was being lazy):

$ cat tst.awk
BEGIN { FS="[:= ]" }
NF {
    if ( $1 == "Chosen" ) {
        user = $4
        chosen = $5
    }
    else {
        avail[$5]
    }
    next
}
{ prt() }
END {
    prt()
    printf "%d users chose available %d times and not available %d times\n", userCnt, availCnt, notAvailCnt
}

function prt() {
    if ( chosen in avail ) {
        availCnt++
        str = ""
    }
    else {
        notAvailCnt++
        str = " not"
    }
    userCnt++
    printf "User %s chose %s which was%s available\n", user, chosen, str
    delete avail
}

Then running it against your new input produces:

$ awk -f tst.awk file
User 75 chose 1655 which was not available
User 10 chose 1301 which was available
User 20 chose 1503 which was available
3 users chose available 2 times and not available 1 times

We can then tweak it to also print the globalID:

$ cat tst2.awk
BEGIN { FS="[:= ]" }
NF {
    if ( $1 == "Chosen" ) {
        user = $4
        chosen = $5
    }
    else if ( $1 == "globalID" ) {
        globalID = $2
    }
    else {
        avail[$5]
    }
    next
}
{ prt() }
END {
    prt()
    printf "%d users chose available %d times and not available %d times\n", userCnt, availCnt, notAvailCnt
}

function prt() {
    if ( chosen in avail ) {
        availCnt++
        str = ""
    }
    else {
        notAvailCnt++
        str = " not"
    }
    userCnt++
    printf "User %s chose %s which was%s available, and had globalID %s\n", user, chosen, str, globalID
    delete avail
}

which outputs:

$ awk -f tst2.awk file
User 75 chose 1655 which was not available, and had globalID 1000
User 10 chose 1301 which was available, and had globalID 1020
User 20 chose 1503 which was available, and had globalID 1030
3 users chose available 2 times and not available 1 times

Hopefully you can see how easy it'd be to just change the print statements to print whatever you actually want to be output (and please don't pipe it to grep or anything else - just do it in awk, it's easy). For example:

$ cat tst3.awk
BEGIN { FS="[:= ]" }
NF {
    if ( $1 == "Chosen" ) {
        user = $4
        chosen = $5
    }
    else if ( $1 == "globalID" ) {
        globalID = $2
    }
    else {
        avail[$5]
    }
    next
}
{ prt() }
END { prt() }

function prt() {
    if ( chosen in avail ) {
        result = "match"
    }
    else {
        result = "nomatch"
    }
    if ( target == result ) {
        print globalID
    }
    delete avail
}

.

$ awk -v target='match' -f tst3.awk file
1020
1030

$ awk -v target='nomatch' -f tst3.awk file
1000
1
  • 1
    Thanks @Ed Morton Jul 27, 2020 at 8:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .