Replace a word in a line with different words
-
I want to replace a particular word in a line with list of words and separate entry should be created for each word.
Let’s consider this line of text - ‘I live in USA’
I have huge list of countries including UK, Canada, Australia, India etc and want to replace USA with every other country and I am expecting a separate line for each value like
I live in UK
I live in Canada
I love in AustraliaPlease help me if there is any work around for the same.Thanks in advance.
-
Notepad++ does not have mail-merge capability built in.
If you search the forum for “mail merge”, you might find some helpful posts with scripts or plugins that will help you. (For example, here is one I wrote last year, which may or may not help in your current situation)
—
addenda: and if your “template” is really as simple as
I live in XXXX
, then it’s actually probably easier to go the other way: copy your file that is a list of countries, and replace each line withI live in
prefix.Also, The answer may change depending on exact format of the data. For example,
I live in XXX. Here are some lines My relative also lives in XXX
Based on your description, that could be interpreted as you wanting
I live in UK. I live in Canada. I live in Australia. Here are some lines My relative also lives in UK My relative also lives in Canada My relative also lives in Australia
or as
I live in UK. Here are some lines My relative also lives in UK I live in Canada. Here are some lines My relative also lives in Canada I live in Australia. Here are some lines My relative also lives in Australia
but the process would be different between them (a mail-merge would work for the second, but not for the first)
----
Useful References
-
Thanks for your suggestion and appreciate your swift response. I would provide my exact requirement in order to help me better.
Change,Version,PAY,PAYC.LB_BRT,EFF_DATE,27/10/2022
Change,Version,PAY,PAYC.LB_BRT,EXP_DATE,28/10/2022
Insert,Version,PAY,PAYC.LB_BRT,PAYC.EFF_DATE,
Insert,Version,PAY,PAYC.LB_BRT,PAYC.EXP_DATE,
Change,Version,PAY,PAYC.LB_BRT,Node,True
Change,Version,PAY,PAYC.LB_BRT,DWFLAG,True
Change,Version,PAY,PAYC.LB_BRT,RDFLAG,TrueLB_BRT should be replaced with 100 other values like NO_OSL, MX_MEX, PE_LIM and as I said previously am expecting separate entries for each value that has been replaced.
So, The above 7 lines should be appended with another 7 lines each for NO_OSL, MX_MEX and so on
-
So a traditional “mail merge” would take some “template” data, e.g.:
Dear <CUSTOMER_TITLE> <CUSTOMER_LAST_NAME>, We would like to invite you or a representative of <CUSTOMER_COMPANY> to join us at the Text Editor Users' Trade Show in Berlin. If possible, we would like to meet you on <MEETING_TIME> in order to review our distribution agreement. I'm looking forward for your reply, <CUSTOMER_FIRST_NAME>. <WRITERS_NAME>, <WRITERS_COMPANY> ---------------------------------------------------
and then some “data table” data:
<CUSTOMER_FIRST_NAME>|<CUSTOMER_LAST_NAME>|<CUSTOMER_TITLE>|<CUSTOMER_COMPANY>|<MEETING_TIME>|<WRITERS_NAME>|<WRITERS_COMPANY> Michael|Smith|Mr.|XYZ, Inc.|21st of August at 3PM|Alan Kilborn|NPP Support Specialists, Inc. Paula|Poundstone|Ms.|ABC, Inc.|22nd of August at 10AM|Peter Jones|NPP Support Specialists, Inc. Shankar|Vedantam|M.|QED, LLC|23rd of August, 4PM|Terry Bradshaw|Broadcasters Unlimited
and then expand the template using the data, into a “result”:
Dear Mr. Smith, We would like to invite you or a representative of XYZ, Inc. to join us at the Text Editor Users' Trade Show in Berlin. If possible, we would like to meet you on 21st of August at 3PM in order to review our distribution agreement. I'm looking forward for your reply, Michael. Alan Kilborn, NPP Support Specialists, Inc. --------------------------------------------------- Dear Ms. Poundstone, We would like to invite you or a representative of ABC, Inc. to join us at the Text Editor Users' Trade Show in Berlin. If possible, we would like to meet you on 22nd of August at 10AM in order to review our distribution agreement. I'm looking forward for your reply, Paula. Peter Jones, NPP Support Specialists, Inc. --------------------------------------------------- Dear M. Vedantam, We would like to invite you or a representative of QED, LLC to join us at the Text Editor Users' Trade Show in Berlin. If possible, we would like to meet you on 23rd of August, 4PM in order to review our distribution agreement. I'm looking forward for your reply, Shankar. Terry Bradshaw, Broadcasters Unlimited ---------------------------------------------------
As you can see, the template is filled with constant text, plus variable-text “tokens” (not my favorite word) in angle brackets, e.g.
<MEETING_TIME>
.The data table consists of a header line that lists all of the tokens, separated by
|
symbols:<CUSTOMER_FIRST_NAME>|<CUSTOMER_LAST_NAME>|<CUSTOMER_TITLE>|<CUSTOMER_COMPANY>|<MEETING_TIME>|<WRITERS_NAME>|<WRITERS_COMPANY>
followed by lines of data, each containing the same number of
|
symbols as the header. Each line after the header contains one set of data with which the template will be expanded.A fairly easy explanation, right? So let’s do a script to make it happen.
-
Let’s call the script
MailMerge.py
:# -*- coding: utf-8 -*- from __future__ import print_function # references: # https://community.notepad-plus-plus.org/topic/24053 from Npp import * import inspect import os from datetime import datetime as dt import re #------------------------------------------------------------------------------- class MM(object): demo_template_str = ''' Dear <CUSTOMER_TITLE> <CUSTOMER_LAST_NAME>, We would like to invite you or a representative of <CUSTOMER_COMPANY> to join us at the Text Editor Users' Trade Show in Berlin. If possible, we would like to meet you on <MEETING_TIME> in order to review our distribution agreement. I'm looking forward for your reply, <CUSTOMER_FIRST_NAME>. <WRITERS_NAME>, <WRITERS_COMPANY> --------------------------------------------------- '''.lstrip() demo_datatable_str = ''' <CUSTOMER_FIRST_NAME>|<CUSTOMER_LAST_NAME>|<CUSTOMER_TITLE>|<CUSTOMER_COMPANY>|<MEETING_TIME>|<WRITERS_NAME>|<WRITERS_COMPANY> Michael|Smith|Mr.|XYZ, Inc.|21st of August at 3PM|Alan Kilborn|NPP Support Specialists, Inc. Paula|Poundstone|Ms.|ABC, Inc.|22nd of August at 10AM|Peter Jones|NPP Support Specialists, Inc. Shankar|Vedantam|M.|QED, LLC|23rd of August, 4PM|Terry Bradshaw|Broadcasters Unlimited '''.lstrip() def __init__(self): self.debug = True if 1 else False self.this_script_name = inspect.getframeinfo(inspect.currentframe()).filename.split(os.sep)[-1].rsplit('.', 1)[0] self.this_script_path_without_ext = inspect.getframeinfo(inspect.currentframe()).filename.rsplit('.', 1)[0] run_demo = self.yes_no_cancel('Run demo mail-merge?\r\n\r\nNo = Let me get to my real data, NOW!') if run_demo is None: return if run_demo: notepad.new() eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] editor.setText(self.demo_template_str.replace('\n', eol)) editor.setSavePoint() template_tab_path = notepad.getCurrentFilename() notepad.new() datatable_tab_path = notepad.getCurrentFilename() editor.setText(self.demo_datatable_str.replace('\n', eol)) editor.setSavePoint() self.expand_template_and_datatable_into_new_tab(template_tab_path, datatable_tab_path) return # end after running the 'demo' for which in [ 'TEMPLATE', 'DATATABLE' ]: while True: tab_path = self.get_user_filetab_choice('Choose {w} filetab by putting an X in the brackets to its left'.format(w=which)) if tab_path is None: if self.yes_no('Could not detect your file choice or maybe you want to abort?\r\n\r\n' 'Select Yes to abort, No to try selecting a file again.'): return # abort continue if which == 'TEMPLATE': template_tab_path = tab_path else: datatable_tab_path = tab_path if template_tab_path == datatable_tab_path: self.mb('You picked the same file for the data as the template; pick again') continue break self.expand_template_and_datatable_into_new_tab(template_tab_path, datatable_tab_path) def expand_template_and_datatable_into_new_tab(self, template_tab_pathname, datatable_tab_pathname): notepad.activateFile(template_tab_pathname) template_str = editor.getText() notepad.activateFile(datatable_tab_pathname) sub_line_list = editor.getText().splitlines() accumulated_expanded_template_str = '' for (sub_row_num, sub_row_contents) in enumerate(sub_line_list): substitution_list = sub_row_contents.split('|') num_data_items = len(substitution_list) if sub_row_num == 0: sub_tag_list = substitution_list[::] # copy list elif num_data_items == len(sub_tag_list): one_expanded_template_str = template_str for j in range(len(sub_tag_list)): one_expanded_template_str = re.sub(sub_tag_list[j], substitution_list[j], one_expanded_template_str) accumulated_expanded_template_str += one_expanded_template_str notepad.new() eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] accumulated_expanded_template_str = self.unify_line_endings(accumulated_expanded_template_str, eol) editor.setText(accumulated_expanded_template_str) def get_user_filetab_choice(self, prompt_str): retval = None file_list = [] view1_file_list = [] pathname_to_avoid_clones_dict = {} for (j, (pathname, buffer_id, index, view)) in enumerate(notepad.getFiles()): if pathname in pathname_to_avoid_clones_dict: continue pathname_to_avoid_clones_dict[pathname] = True view_addendum = '' if notepad.isSingleView() else ' (view {})'.format(view + 1) entry = '[ ] {f}{v}'.format(v=view_addendum, f=self.filename_from_pathname(pathname)) file_list.append(entry) if view == 0 else view1_file_list.append(entry) file_list = file_list[::-1] # reverse the list file_list.extend(view1_file_list) user_input = self.prompt(prompt_str, '\r\n'.join(file_list)) if user_input is not None: m = re.search(r'\[\s*\S+\s*\]\s+([^\r\n]+)', user_input) if m: filename = m.group(1) index = filename.find(' (view ') if index != -1: filename = filename[:index] retval = self.pathname_from_filename_on_tab(filename) return retval def filename_from_pathname(self, p): f = p.rsplit(os.sep, 1)[-1] return f def pathname_from_filename_on_tab(self, f): retval = None for (pathname, buffer_id, index, view) in notepad.getFiles(): tab_f = pathname.rsplit(os.sep, 1)[-1] if f == tab_f: retval = pathname break return retval def unify_line_endings(self, text, desired_line_ending='\r\n'): any_line_ending_regex = r'\r(?!\n)|((?<!\r)\n)|\r\n' retval = re.sub(any_line_ending_regex, desired_line_ending, text) return retval def print(self, *args, **kwargs): try: self.print_first except AttributeError: self.print_first = True if self.print_first: console.show() # this will put input focus in the PS console window, at the >>> prompt #console.clear() editor.grabFocus() # put input focus back into the editor window self.print_first = False d_tag = '' if 'debug' in kwargs: now = dt.now() hr = now.strftime('%I') if hr[0] == '0': hr = hr[1:] ap = 'p' if now.strftime('%p')[0] == 'P' else 'a' ms = now.strftime('%f')[:3] d_tag = now.strftime('<%a{hr}:%M:%S{ap}.{ms}>'.format(hr=hr, ap=ap, ms=ms)) del kwargs['debug'] print(self.__class__.__name__ + d_tag + ':', *args, **kwargs) def dprint(self, *args, **kwargs): # debug print function if self.debug: kwargs['debug'] = True self.print(*args, **kwargs) def mb(self, msg, flags=0, title=''): # a message-box function return notepad.messageBox(msg, title if title else self.this_script_name, flags) def yes_no(self, question_text): # returns True(Yes), False(No) answer = self.mb(question_text, MESSAGEBOXFLAGS.YESNO, self.this_script_name) return True if answer == MESSAGEBOXFLAGS.RESULTYES else False def yes_no_cancel(self, question_text): # returns True(Yes), False(No), or None(Cancel) retval = None answer = self.mb(question_text, MESSAGEBOXFLAGS.YESNOCANCEL, self.this_script_name) if answer == MESSAGEBOXFLAGS.RESULTYES: retval = True elif answer == MESSAGEBOXFLAGS.RESULTNO: retval = False return retval def prompt(self, prompt_text, default_text=''): if '\n' not in prompt_text: prompt_text = '\r\n' + prompt_text prompt_text += ':' return notepad.prompt(prompt_text, self.this_script_name, default_text) #------------------------------------------------------------------------------- if __name__ == '__main__': MM()
–
Moderator EDIT (2024-Jan-14): The author of the script has found a fairly serious bug with the code published here for those that use Mac-style or Linux-style line-endings in their files. The logic for Mac and Linux was reversed, and thus if the script was used on one type of file, the line-endings for the opposite type of file could end up in the file after the script is run. This is insidious, because unless one works with visible line-endings turned on, this is likely not noticed. Some detail on the problem is HERE. The script above has been corrected per that instruction. -
-
Running the script, we are prompted:
Let’s do the demo, first. This opens 3 new file tabs; these will be filled with content from the example in my earlier posting. This is so that if you forget how the script works after a time of disuse, you can quickly orient yourself to how you have to construct your data.
Basically, and now we’re talking about non-demo running, you put the “template” text content in one tab, and the “data table” content in another tab, and then run the script.
The script will prompt you through picking the 2 N++ filetabs containing your information:
…select it with an
x
, click ok, and……same thing, make a selection, press OK…
and then a new tab will be created with your expanded-out template.
-
So how does @Prasanth-Varadharaj use this to achieve his goal?
Maybe he creates a template file called
templ.txt
containing:Change,Version,PAY,PAYC.LB_BRT,EFF_DATE,27/10/2022 Change,Version,PAY,PAYC.LB_BRT,EXP_DATE,28/10/2022 Insert,Version,PAY,PAYC.LB_BRT,PAYC.EFF_DATE, Insert,Version,PAY,PAYC.LB_BRT,PAYC.EXP_DATE, Change,Version,PAY,PAYC.LB_BRT,Node,True Change,Version,PAY,PAYC.LB_BRT,DWFLAG,True Change,Version,PAY,PAYC.LB_BRT,RDFLAG,True
He needs to turn
LB_BRT
into a recognizable token, so he does a replace onLB_BRT
with<LB_BRT>
to get:Next he sets up his data table info, say, in
dat_tab.txt
, with content:Next, running the script and NOT doing the demo, prompts:
and then:
After the final OK, the expanded template data is generated in a new tab:
Change,Version,PAY,PAYC.NO_OSL,EFF_DATE,27/10/2022 Change,Version,PAY,PAYC.NO_OSL,EXP_DATE,28/10/2022 Insert,Version,PAY,PAYC.NO_OSL,PAYC.EFF_DATE, Insert,Version,PAY,PAYC.NO_OSL,PAYC.EXP_DATE, Change,Version,PAY,PAYC.NO_OSL,Node,True Change,Version,PAY,PAYC.NO_OSL,DWFLAG,True Change,Version,PAY,PAYC.NO_OSL,RDFLAG,True Change,Version,PAY,PAYC.MX_MEX,EFF_DATE,27/10/2022 Change,Version,PAY,PAYC.MX_MEX,EXP_DATE,28/10/2022 Insert,Version,PAY,PAYC.MX_MEX,PAYC.EFF_DATE, Insert,Version,PAY,PAYC.MX_MEX,PAYC.EXP_DATE, Change,Version,PAY,PAYC.MX_MEX,Node,True Change,Version,PAY,PAYC.MX_MEX,DWFLAG,True Change,Version,PAY,PAYC.MX_MEX,RDFLAG,True Change,Version,PAY,PAYC.PE_LIM,EFF_DATE,27/10/2022 Change,Version,PAY,PAYC.PE_LIM,EXP_DATE,28/10/2022 Insert,Version,PAY,PAYC.PE_LIM,PAYC.EFF_DATE, Insert,Version,PAY,PAYC.PE_LIM,PAYC.EXP_DATE, Change,Version,PAY,PAYC.PE_LIM,Node,True Change,Version,PAY,PAYC.PE_LIM,DWFLAG,True Change,Version,PAY,PAYC.PE_LIM,RDFLAG,True
-
@Alan-Kilborn
That’s an wonderful explanation. Thank you so much for your time.Could you please let me know how did you execute the python script? Hope you had a plugin in notepad++, correct me If am wrong.
And, will any online compiler help to achieve this result?
-
@Prasanth-Varadharaj said in Replace a word in a line with different words:
Could you please let me know how did you execute the python script?
Usually when I post a script I also post a link to the FAQ entry that discusses how to set up and use a script; unfortunately I neglected to do so this time. Here’s that LINK.
-
-
If you’ve used a script in this thread, you might want to double check your copy of it for a bug I’ve discovered.
Look to previous postings in this topic thread where the script has been changed – find the textmoderator edit (2024-Jan-14)
.
There’s a link there that describes the bug in more detail, and shows what needs to be changed in an old copy (or you can simply grab a copy of the current version).