Help wanted with REGEX Search
-
Hi there, longtime Notepad++ user here, looking for a bit of help.
I need to search, and replace it as illustrated below. The first number is the line number in the program, the START uses the first P[i] and the END uses the second P[j], the i,j values do need to be copied, the extra numbers do not.
5: CALL -INST_EASYAW_START(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
And replace it with
5:L P[4] 100mm/sec FINE
: Weld Start[1,1];And then
11: CALL -INST_EASYAW_END(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
To
11:L P[5] WELD_SPEED FINE
: Weld End[1,1] ;I’ve played with regex searches but cannot seem to get the right format.
Thanks in advance.
Ian
-
Something I am unclear about: Why do you need regex? If the first line you want to change always starts with
5:
, and that number before the colon is the line number, there will be only one match per file. In which case, just go to line 5, make the edit. Then go to line 11, then make the edit.If you really mean that your file will have many lines that contain
CALL -INST_EASYAW_START
, and you want all of them to be replaced, and many lines withCALL -INST_EASYAW_END
and you want all of them to be replaced, then regex is the right tool for the job. But you need to be more explicit, because the obvious reading of your question says there’s only one of each in the file. If you do reply with more clarification, and it does need to be a regex, then please give a slightly longer data set, with some lines that will match and be transformed, and others that won’t match and won’t be transformed. Otherwise, we’re just trying to guess what you really want, and we’ll get it wrong, and then there will be much back-and-forth, wasting everyone’s time.Also, I highly recommend using the Template for Search/Replace Questions to make sure that the forum doesn’t corrupt your example data.
But as a first guess:
FIND =
(?-s)^(\d+): CALL -INST_EASYAW_START\(P.(\d+).*$
REPLACE =$1:L P[$2] 100mm/sec FINE\r\n: Weld Start[1,1];
then
FIND =(?-s)^(\d+): CALL -INST_EASYAW_END\(P.\d+.,P.(\d+)..*$
REPLACE =$1:L P[$2] WELD_SPEED FINE\r\n: Weld End[1,1];
This comes close to what I think you want:
this:5: CALL -INST_EASYAW_START(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ; 11: CALL -INST_EASYAW_END(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ; 55: CALL -INST_EASYAW_START(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ; 110: CALL -INST_EASYAW_END(P[4],P[5],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
becomes
5:L P[4] 100mm/sec FINE : Weld Start[1,1]; 11:L P[5] WELD_SPEED FINE : Weld End[1,1]; 55:L P[4] 100mm/sec FINE : Weld Start[1,1]; 110:L P[5] WELD_SPEED FINE : Weld End[1,1];
----
Useful References
-
@ianchaykowski said in Help wanted with REGEX Search:
I need to search, and replace it as illustrated below. The first number is the line number in the program, the START uses the first P[i] and the END uses the second P[j], the i,j values do need to be copied, the extra numbers do not.
As per @PeterJones response, it was unclear, although I have taken a leap of faith here in thinking you do mean that there are lots of lines with different line numbers at the start.
So my solution, using the Replace function and having the search mode set to “regular expression” is:
Find What:(?-s)^(\d+:)\x20*CALL\x20*-INST_EASYAW_(START)?(END)?\((P\[\d+\]),(P\[\d+\]).+(\R)
Replace With:\1L (?{2}\4 100mm/sec FINE\6)(?{3}\5 WELD_SPEED FINE\6): WELD Start[1,1];\6
Before you run it, please make sure there is a final blank line as my regex requires that. I’ll explain the process my regex uses:
(?-s)^
the DOT character does not include end of lines (CR and/or LF) ^ is “start of line”.
(\d+:)\x20*CALL\x20*-INST_EASYAW_
we capture the line number and also parse the static text which may (or may not) contain spaces at certain points (\x20).
(START)?(END)?
here we are looking for either the START or END text. By capturing each instance separately we can test in the replacement and adjust the result accordingly.
\((P\[\d+\]),(P\[\d+\])
here we capture both P[] instances in separate groups.
.+(\R)
we parse the remaining text and capture the CR and/or LF sequence. Since I didn’t know if this was a Windows text file (or possibly Mac/Linux based) I capture this here so I can return the exact same type in the output. Since I expect a CR and/or LF, that’s why there must be a final blank line in the file.
In the replacement field of the regex we have:
\1L
we return the first capture group i.e. line number (\1) and the L and a space.
(?{2}\4 100mm/sec FINE\6)
if the 2nd capture group found the START text we return the text as you showed it, using the first P[] number (\4). Amongst that is the CR and/or LF sequence as we captured in the find field (\R).
(?{3}\5 WELD_SPEED FINE\6)
as per the previous using the 3rd capture group, but here we expect the END text to have been found and we return the second P[] number (\5).
: WELD Start[1,1];\6
here the remaining text which seems to be the same for both START and END is returned followed by another CR and/or LF sequence.Finally the added blank line at the end of the file should be removed again.
Mine is more complicated than @PeterJones one since I have combined both the START and END replacements into 1 regex.
Terry
-
Sorry for the confusion, I was trying to simplify the request, basically I have an instruction set that needs to change, here’s a bigger snip of the code:
16: CALL -INST_EASYAW_START(P[17],P[18],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
17:L P[19] WELD_SPEED CNT100 ;
18:C P[20]
: P[21] WELD_SPEED CNT100 ;
19:L P[22] WELD_SPEED CNT100 ;
20:C P[23]
: P[24] WELD_SPEED CNT100 ;
21: CALL -INST_EASYAW_END(P[17],P[18],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
22:J P[25] 100% FINE ;
23:J P[26] 100% FINE ;
24:L P[27] 1000mm/sec FINE ;
25: CALL -INST_EASYAW_START(P[28],P[29],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;
26:L P[30] WELD_SPEED CNT100 ;
27:C P[31]
: P[32] WELD_SPEED CNT100 ;
28:L P[33] WELD_SPEED CNT100 ;
29:C P[34]
: P[35] WELD_SPEED CNT100 ;
30: CALL -INST_EASYAW_END(P[28],P[29],200,16,18,395,1,0,0,0,0,365,1,0,0,0,0,.4,0,1) ;The Start and End need to keep the same positional values, but programs will have in excess of 300 lines, the start uses the first point, then end uses the last.
I see a couple recommendations you guys made and I’ll see if I can get them to work tomorrow.
Thanks for the quick response. I’ll maybe try to upload a color coded version as an image if more detail is needed.
Ian
-
@terry-r Thanks Terry, it looks like this might preserved the point data, I’ll try it tomorrow!
-
@ianchaykowski said in Help wanted with REGEX Search:
Thanks Terry, it looks like this might preserved the point data, I’ll try it tomorrow!
If it hasn’t then you need to insert your example data in the correct way. The previous post was not the right way. Read @PeterJones post and the link he provided to one of our FAQ posts that outlines the reason why you need to insert example data the correct way.
Terry
-
@terry-r
Both solutions look promising, but I am fighting a formatting problem on the site, so I’ll try to literally follow the template just so I’ve done it right at least once :).There were 2 leading spaces on the line numbers that did not paste last time.
Instead of using one of the programs I’m trying to fix I generated a simple example of 3 short welds.
Here is the data I currently have (“before” data):
/MN 1:L P[1] 1000mm/sec FINE ; 2:L P[2] 250mm/sec FINE ; 3: CALL -INST_EASYAW_START(P[3],P[4],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.4,0,1) ; 4: CALL -INST_EASYAW_END(P[3],P[4],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.4,0,1) ; 5:L P[5] 1000mm/sec FINE ; 6:L P[6] 1000mm/sec FINE ; 7: CALL -INST_EASYAW_START(P[7],P[8],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.3,0,1) ; 8: CALL -INST_EASYAW_END(P[7],P[8],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.3,0,1) ; 9:L P[9] 1000mm/sec FINE ; 10:L P[10] 1000mm/sec FINE ; 11: CALL -INST_EASYAW_START(P[11],P[12],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.2,0,1) ; 12: CALL -INST_EASYAW_END(P[11],P[12],200,29,11,380,22,0,0,0,0,360,21,0,0,0,0,.2,0,1) ; 13:L P[13] 1000mm/sec FINE ;
Here is how I would like that data to look (“after” data):
/MN 1:L P[1] 1000mm/sec FINE ; 2:L P[2] 250mm/sec FINE ; 3:L P[3] 100mm/sec FINE : Weld Start[1,1] ; 4:L P[4] WELD_SPEED FINE : Weld End[1,1] ; 5:L P[5] 1000mm/sec FINE ; 6:L P[6] 1000mm/sec FINE ; 7:L P[7] 100mm/sec FINE : Weld Start[1,1] ; 8:L P[8] WELD_SPEED FINE : Weld End[1,1] ; 9:L P[9] 1000mm/sec FINE ; 10:L P[10] 1000mm/sec FINE ; 11:L P[11] 100mm/sec FINE : Weld Start[1,1] ; 12:L P[12] WELD_SPEED FINE : Weld End[1,1] ; 13:L P[13] 1000mm/sec FINE ;
Thanks again, I’m amazed at how quick the responses were, and this will save days of work. Manually changing one line takes about 10 clicks, converting to ascii and back makes it much easier.
Ian
-
There were 2 leading spaces on the line numbers that did not paste last time.
So originally you had two spaces but now your example desired output shows four. I will assume you really mean four this time.
(Fortunately, because of hints I saw when I peeked at your markdown, I had already thought about how to solve the indentation problem, as can be seen by hovering over my dots above; I just had to adjust it slightly because I wasn’t allowing spaces before the colon on the actually-numbered lines.)
I would do your whole process in 3 stages, to avoid getting too confused on any step.
-
Do the START replacement (similar to what I had before, but modified to allow spaces before the numbers):
FIND =(?-s)^(\x20*\d+):\x20*CALL -INST_EASYAW_START\(P.(\d+).*$
REPLACE =$1:L P[$2] 100mm/sec FINE\r\n: Weld Start[1,1];
This will not have spaces before the inserted:
lines … yet. That’s step 3.
(in the regex, I used\x20
for spaces, because that way there’s no uncertainty during copy/paste) -
Do the END replacement
FIND =(?-s)^(\x20*\d+):\x20*CALL -INST_EASYAW_END\(P.\d+.,P.(\d+)..*$
REPLACE =$1:L P[$2] WELD_SPEED FINE\r\n: Weld End[1,1];
-
Use this fancy expression to essentially count the number of characters (space or digit) before the colon. This one will do up to 4. If you have more than 9999 lines, it’s up to you to figure out what the pattern is doing, and extend the pattern.
FIND =(?-s)^([\x20\d])([\x20\d])?([\x20\d])?([\x20\d])?:.*\R(?=:)
REPLACE =$0(?4 :(?3 :(?2 :(?1 ))))
-
-
Hello, @ianChaykowski, @peterjones, @terry-r and All,
From your last post, here is one solution which do give the expected results, included case of letters, from your original data :
SEARCH
(?-s)^(\x20+)(\d+)(: CALL -INST_EASYAW_)START.+\R(\x20+)(\d+)\3END.+\R
REPLACE
\1\2:L P[\2] 100mm/sec FINE\r\n : Weld Start[1,1] ;\r\n\4\5:L P[\5] WELD_SPEED FINE\r\n : Weld End[1,1] ;\r\n
( case of Windows files )or
REPLACE
\1\2:L P[\2] 100mm/sec FINE\n : Weld Start[1,1] ;\n\4\5:L P[\5] WELD_SPEED FINE\n : Weld End[1,1] ;\n
( case of Unix files )Best Regards,
guy038
-
@peterjones said in Help wanted with REGEX Search:
$1:L P[$2] WELD_SPEED FINE\r\n: Weld End[1,1];
That worked beautifully, thanks so much