Find and Replace with increments
-
I have a text file that is made up of roughly 500+ of the following repeating format:
{ "valueSource": "opc", "historyTimeDeadband": 5, "opcItemPath": "ns\u003d1;s\u003d[Extruder19]Master_die_zone_1.PVHAlarm", "historicalDeadband": 0.5, "alarms": [ { "setpointA": 1.0, "name": "Master die zone 1 PVHAlarm", "priority": "High", "displayPath": "Extruder19" } ], "historicalDeadbandStyle": "Discrete", "tagGroup": "Default", "historyTagGroup": "Alarm Historical", "tagType": "AtomicTag", "dataType": "Boolean", "historyProvider": "BOL_IgnitionDB", "name": "Master_die_zone_1_PVHAlarm", "historyEnabled": false, "sampleMode": "TagGroup", "opcServer": "Ignition OPC UA Server" },
For this, they are all the exact same right now, but I want to change some parts of it. Wherever it says “zone_1” (Lines 4,9, and 20) it need to replace it with “zone” + incrementing numbers, so the second group of this would read “zone_2”, the third will read “zone_3” and so on. What is a way I can do that using notepad++?
-
With just Notepad++ and nothing else, you cannot: the replacement engine cannot “auto increment”. If you are willing to use a plugin, it’s easy.
You can install the PythonScript plugin, and use the example
add_1
that’s in the documentation; you’d have to change the search regular expression in the script to suit your needs (off the top of my head, without trying, it would be something liker'zone_(\d+)'
for the search string)This FAQ entry describes how to install the PythonScript plugin and create a new script in PythonScript. And using Plugins > Python Script > Context-Help will take you to the documentation, and searching that documentation for
add_1
will take you to the example script.Please note that the example in the documentation adds one to the number found in the search; what you want is a
counter
that adds one to the previous value of the counter and replaces the found string with a string based on that counter instead.You can search this forum for examples of
add_1
and related pythonscript replacements … and I think this post probably contains close to what you want in terms of thecounter
. -
@peterjones thank you for the detailed response, Apologize if this is a stupid question but how would I make the python code for notepad++? I have used python before but never for notepad++ so I am not sure how it works at all. Would I just write “editor.rereplace(r’zone (\d+)', add_1)” on the python file?
-
how would I make the python code for notepad++? …
I rather thought I already answered that in my last post and the FAQ entry that I pointed you to. Plus the other discussion, with the
counter
example has the step-by-step detailed instructions embedded in the script to copy/paste. I am not sure how much more explicit about the process that I can be.Would I just write … on the python file?
If I assume that by “on the python file” meant “inside the file that I created when I followed the instructions in the FAQ, and on the line that currently has the
editor.rereplace
from that script”, then yes.When I noticed that you had typed without an underscore in your reply, I looked back and now see that in your example data, lines 4 and 20 have the underscore but line 9 does not, so my guess at an expression will definitely not work for you. And that there is more than one instance of
zone_#
in each block, so I am now assuming that you really want to maintain the same # within each top-level{...}
block.That’s much more complicated than I originally understood it, and a simple change to the
counter
example won’t be sufficient for your needs. -
I think this script will do what you want
# encoding=utf-8 """https://community.notepad-plus-plus.org/topic/23149/find-and-replace-with-increments/4 This will start by matching text from `{` at the beginnig of a line to `}` or `},` at the beginning of a line Inside those groups, it will replace all "zone_#" or "zone #" with the value of the counter The counter will increment between `{...}` groups """ from Npp import * import re counter = 1 def replace_group(m): global counter out = re.sub(r'(?<=zone[ _])\d+', str(counter), m.group(0)) counter = counter + 1 return out console.clear() editor.beginUndoAction() editor.rereplace(r'(?s)^{\h*$.*?^},?\h*$', replace_group) editor.endUndoAction()
The
editor.rereplace
line matches from{
at the beginning of a line to}
or},
at the beginning of a line. It then callsreplace_group()
on that match. The second function does the search-and-replace inside that group, looking forzone
followed by either_
or space, followed by one or more digits, and replaces those digits with the current value of the counter. Every group of{
to},
will increment the counter by one, so each chunk will get a unique number, but use the same number inside.Assumptions:
- That your example data isn’t missing leading spaces, because the regex assumes the
{
and},
are at the beginning of the line.- That there aren’t any other
{
and},
at the beginning of lines embedded inside (so nicely indented and properly formulated json)
- That there aren’t any other
- That
zone_1
andzone 1
within a single {…} block should all get the same counter value - That you don’t have any
zone_###
inside your blocks that you don’t want changed (you didn’t show any, but…)
- That your example data isn’t missing leading spaces, because the regex assumes the
-