4

I have two files, A and B.

File A is a letter, as below, which contains several placeholder strings on each line, like <@userid>.

<@U39RFF91U> for all the help in this project!

Thanks for your help to enhance the data quality <@U2UNRTLBV> <@U39RFF91U> <@U2UQCN023>!
Thanks for <@U38F4TBQ9> <@U38F5PQ73> <@U38F747CZ> <@U39RT0G07> and <@U2UQ17U20> ’s great work at the New Product!


Successful release! <@U2WHAAU9H> <@U2ML3C551> <@U38F4TBQ9> <@U38F747CZ> <@U39RT0G07> <@U2UQ17U20> <@U38F5PQ73> <@U2N64H7C6>!

Praise <@U2X0APW3Y> for going above and beyond to help with the retail campaign!

File B is a mapping table, mapping all user IDs to each user's name:

U39RFF91U  Person1
U2UNRTLBV  Person2

I'd like to work out a final file, C, with the content from the letter in A, but with all placeholders replaced by the corresponding content from the mapping table in file B.

Any idea how to do it via shell script on Linux?

Kusalananda
  • 333,661
Glen31
  • 51
  • Can you paste a sample output, how it is required – upkar Jan 26 '17 at 11:54
  • Is the required output. for checking defind person 1 as upkar. Also user name is not hardcoded it will refer from file B only Upkar. for all the help in this project!

    Thanks for your help to enhance the data quality Karup Upkar <@U2UQCN023>! Thanks for <@U38F4TBQ9> <@U38F5PQ73> <@U38F747CZ> <@U39RT0G07> and <@U2UQ17U20> .s great work at the New Product!

    Successful release! <@U2WHAAU9H> <@U2ML3C551> <@U38F4TBQ9> <@U38F747CZ> <@U39RT0G07> <@U2UQ17U20> <@U38F5PQ73> <@U2N64H7C6>!

    Praise <@U2X0APW3Y> for going above and beyond to help with the retail campaign!

    – upkar Jan 26 '17 at 12:13
  • Is it possible names map table to have spaces in user name and/or user id? – George Vasiliou Jan 26 '17 at 13:02

4 Answers4

5

You may transform the mappings into a sed editing script like this:

$ sed -r 's#^([^[:blank:]]*)[[:blank:]]+(.*)#s/<@\1>/\2/g#' user_map.txt >script.sed

Given the example, this will produce script.sed with the contents

s/<@U39RFF91U>/Person1/g
s/<@U2UNRTLBV>/Person2/g

You may then apply this editing script to the text file:

$ sed -f script.sed letter.txt >completed_letter.txt
Kusalananda
  • 333,661
1

Can be done either with sed or even using just bash tools .

Classic bash solution:

var="$(cat file.txt)";while read -r id name;do var="${var//@$id/$name}";done<mapfile.txt;echo "$var"

You can append >newfile.txt to the last command to send the final text in a newfile.

Sed solution with writting changes to the same file:

while read -r id name;do sed -i "s/\@$id/$name/g" textfile.txt;done<mapfile.txt

This solution may perform slower if mapfile / text file are quite large, since external app sed is called for every entry found stored in map file.

Both solutions work ok with your sample.

$ cat b.txt
<@U39RFF91U> for all the help in this project!
Thanks for your help to enhance the data quality <@U2UNRTLBV> <@U39RFF91U> <@U2UQCN023>!

$ cat c.txt
U39RFF91U  Person1
U2UNRTLBV  Person2

$ var="$(cat b.txt)";while read -r id name;do var="${var//@$id/$name}";done<c.txt #Batch Solution
$ echo "$var" 
<Person1> for all the help in this project!
Thanks for your help to enhance the data quality <Person2> <Person1> <@U2UQCN023>!

$ while read -r id name;do sed -i "s/\@$id/$name/g" b.txt;done<c.txt #SED solution
$ cat b.txt
<Person1> for all the help in this project!
Thanks for your help to enhance the data quality <Person2> <Person1> <@U2UQCN023>!
1

File B:

U39RFF91U  Person1
U2UNRTLBV  Person2

File A as noted, with e.g. <@U39RFF91U> in the text.


Simple working code (one-liner):

sed -e "$(sed -E 's_^([^[:space:]]+)[[:space:]]+(.*)$_s/<@\1>/\2/g_' file_B)" file_A

Essentially equivalently:

sed -e "$(sed 's_  *_>/_;s_^_s/<@_;s_$_/g_' file_B)" file_A

(Only difference is no handling of tab characters.)


You might want to proofread the result. It looks like you will very probably be missing some commas for it to be good English.

Wildcard
  • 36,499
0
sed -r 's#(\S+)\s+(.*)#s/<@\1>/\2/g#' map | sed -f- data
mug896
  • 965
  • 9
  • 12