Igor Torres
Igor Torres

Reputation: 55

how to replace everything except string of interest

file.txt

fruits:banana,apple,grape,limon,orange,tomate,
fruits:apple,limon,
fruits:banana,grape,limon,
fruits:orange,tomate,grape,
fruits:banana,
fruits:apple,
fruits:banana,apple,

I need to replace everything that is different than "banana" for FRUIT, and get output like this:

fruits:banana,FRUIT,FRUIT,FRUIT,FRUIT,FRUIT,
fruits:FRUIT,FRUIT,
fruits:banana,FRUIT,FRUIT,
fruits:FRUIT,FRUIT,FRUIT,
fruits:banana,
fruits:FRUIT,
fruits:FRUIT,apple,

I tried using awk, but I can only replace the fields of specific strings.

Example replace all strings "apple" by fruit2, or all strings "apple" by fruit2 and all strings "tomate"or "orange" by fruit3

awk -F":" '{ gsub(/apple/,"FRUIT2",$2); print }' OFS="," file.tx

or

awk -F":" '{ gsub(/apple/,"FRUIT2",$2);;gsub(/tomate|orange/,"FRUIT3",$2); print }' OFS="," file.txt |sed "s/./:/7"

fruits:banana,FRUIT2,grape,limon,FRUIT3,FRUIT3,
fruits:FRUIT2,limon,
fruits:banana,grape,limon,
fruits:FRUIT3,FRUIT3,grape,
fruits:banana,
fruits:FRUIT2,
fruits:banana,FRUIT2

but I really need is to replace everything that is different from that for any string, ex: fruit4

How to generate output like this?

fruits:FRUIT4,FRUIT2,FRUIT4,FRUIT4,FRUIT3,FRUIT3,
fruits:FRUIT2,FRUIT4,
fruits:FRUIT4,FRUIT4,FRUIT4,
fruits:FRUIT3,FRUIT3,FRUIT4,
fruits:FRUIT4,
fruits:FRUIT2,
fruits:FRUIT4,FRUIT2

Upvotes: 1

Views: 180

Answers (3)

anubhava
anubhava

Reputation: 785721

This awk should work:

awk -F, -v OFS=, '{
   for (i=1; i<=NF; i++)
     if ($i !~ /(^|:)banana$/)
        sub(/[^:]+$/, "FRUIT", $i)
} 1' file

Output:

fruits:banana,FRUIT,FRUIT,FRUIT,FRUIT,FRUIT,
fruits:FRUIT,FRUIT,
fruits:banana,FRUIT,FRUIT,
fruits:FRUIT,FRUIT,FRUIT,
fruits:banana,
fruits:FRUIT,
fruits:banana,FRUIT,

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204259

If you'd like some flexibility in being able to specify your mapping of old to new names on the command line:

$ cat tst.awk
BEGIN {
    FS="[:,]"; OFS=","
    split(map,t)
    for (i=1; i in t; i+=2) {
        m[t[i]] = t[i+1]
    }
}
{
    printf "%s:", $1
    for (i=2;i<=NF;i++) {
        if ($i in m )      { $i = m[$i] }
        else if ("*" in m) { $i = m["*"] }
        printf "%s%s", $i, (i<NF?OFS:ORS)
    }
}

.

$ awk -v map='apple,FRUIT2,tomate,FRUIT3,*,FRUIT4' -f tst.awk file
fruits:FRUIT4,FRUIT2,FRUIT4,FRUIT4,FRUIT4,FRUIT3,FRUIT4
fruits:FRUIT2,FRUIT4,FRUIT4
fruits:FRUIT4,FRUIT4,FRUIT4,FRUIT4
fruits:FRUIT4,FRUIT3,FRUIT4,FRUIT4
fruits:FRUIT4,FRUIT4
fruits:FRUIT2,FRUIT4
fruits:FRUIT4,FRUIT2,FRUIT4

$ awk -v map='apple,BAZINGA,*,VEGGIE' -f tst.awk file
fruits:VEGGIE,BAZINGA,VEGGIE,VEGGIE,VEGGIE,VEGGIE,VEGGIE
fruits:BAZINGA,VEGGIE,VEGGIE
fruits:VEGGIE,VEGGIE,VEGGIE,VEGGIE
fruits:VEGGIE,VEGGIE,VEGGIE,VEGGIE
fruits:VEGGIE,VEGGIE
fruits:BAZINGA,VEGGIE
fruits:VEGGIE,BAZINGA,VEGGIE

$ awk -v map='apple,FRUIT2,tomate,FRUIT3' -f tst.awk file
fruits:banana,FRUIT2,grape,limon,orange,FRUIT3,
fruits:FRUIT2,limon,
fruits:banana,grape,limon,
fruits:orange,FRUIT3,grape,
fruits:banana,
fruits:FRUIT2,
fruits:banana,FRUIT2,

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 247042

To make the process automated, you can do

awk -F '[:,]' -v OFS=, '
    {
        for (i=2; i<=NF; i++) 
            if ($i)
                if (seen[$i])
                    $i = seen[$i]
                else 
                    $i = seen[$i] = "FRUIT" ++n
        sub(OFS, ":")
        print
    }
    END {
        print "map:"
        for (key in seen)
            print key "\t" seen[key]
    }
' file
fruits:FRUIT1,FRUIT2,FRUIT3,FRUIT4,FRUIT5,FRUIT6,
fruits:FRUIT2,FRUIT4,
fruits:FRUIT1,FRUIT3,FRUIT4,
fruits:FRUIT5,FRUIT6,FRUIT3,
fruits:FRUIT1,
fruits:FRUIT2,
fruits:FRUIT1,FRUIT2,
map:
orange  FRUIT5
tomate  FRUIT6
apple   FRUIT2
limon   FRUIT4
banana  FRUIT1
grape   FRUIT3

Upvotes: 1

Related Questions