MOHAMED
MOHAMED

Reputation: 43558

make a change on the string based on mapping

I have the following string format

str="aaa.[any_1].bbb.[any_2].ccc"

I have the following mapping

map1:

any_1 ==> 1
cny_1 ==> 2

map2

any_2 ==> 1
bny_2 ==> 2
cny_2 ==> 3

What's the best command to execute on the str with taking account the above mapping in order to get

$ command $str
aaa.1.bbb.1.ccc

Upvotes: 1

Views: 118

Answers (5)

chw21
chw21

Reputation: 8140

Update: I now think that I didn't understand the question correctly, and my solution therefore is wrong. I'm leaving it in here because I don't know if parts of this answer will be helpful to your question, but I encourage you to look at the other answers first.

Not sure what you mean. But here's something:

any_1="1"
any_2="2"
str="aaa.${any_1}.bbb.${any_2}.ccc"
echo $str

The curly brackets tell the interpreter where the variable name ends and the normal string resumes. Result:

aaa.1.bbb.2.ccc

You can loop this:

for any_1 in {1..2}; do
    for any_2 in {1..3}; do
        echo aaa.${any_1}.bbb.${any_2}.ccc
    done
done

Here {1..3} represents the numbers 1, 2, and 3. Result

aaa.1.bbb.1.ccc
aaa.1.bbb.2.ccc
aaa.1.bbb.3.ccc
aaa.2.bbb.1.ccc
aaa.2.bbb.2.ccc
aaa.2.bbb.3.ccc

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204218

$ cat tst.awk
BEGIN {
    FS=OFS="."
    m["any_1"]=1; m["cny_1"]=2
    m["any_2"]=1; m["bny_2"]=2; m["cny_2"]=3
    for (i in m) map["["i"]"] = m[i]
}
{
    for (i=1;i<=NF;i++) {
        $i = ($i in map ? map[$i] : $i)
    }
    print
}
$ awk -f tst.awk <<<'aaa.[any_1].bbb.[any_2].ccc'
aaa.1.bbb.1.ccc

Upvotes: 0

ring bearer
ring bearer

Reputation: 20793

I have upvoted @chw21's answer as it promotes - right tool for the problem scenario. However,

You can devise a perlbased command based on the following.

#!/usr/bin/perl
use strict;
use warnings;

my $text = join '',<DATA>;
my %myMap = (
 'any_1' => '1',
 'any_2' => '2'
);

$text =~s/\[([^]]+)\]/replace($1)/ge;

print $text;

sub replace {
 my ($needle) = @_;
 return "\[$needle\]" if ! exists $myMap{ lc $needle};
 return $myMap{lc $needle};
}

__DATA__
aaa.[any_1].bbb.[any_2].ccc

Only thing that requires a bit of explanation is may be the regex,it matches text that comes between square brackets and sends the text to replace routine. In replace routine, we get mapped value from map corresponding to its argument.

Upvotes: 0

NeronLeVelu
NeronLeVelu

Reputation: 10039

{
 echo "${str}"
 cat Map1
 cat Map2
} | sed -n '1h;1!H;$!d
x
s/[[:space:]]*==>[[:space:]]*/ /g
:a
s/\[\([^]]*\)\]\(.*\)\n\1 \([^[:cntrl:]]*\)/\3\2/
ta
s/\n.*//p'
  • you could use several mapping, not limited to 2 (even and find to cat every mapping found).
  • based on fact that alias and value have no space inside (can be adapted if any)

Upvotes: 0

choroba
choroba

Reputation: 242038

Turn your map files into sed scripts:

 sed 's%^%s/%;s% ==> %/%;s%$%/g%' map?

Apply the resulting script to the input string. You can do it directly by process substitution:

sed 's%^%s/%;s% ==> %/%;s%$%/g%' map? | sed -f- <(echo "$str")

Output:

aaa.[1].bbb.[1].ccc

Upvotes: 1

Related Questions