Inserting a line when block of text matches certain conditions

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Inserting a line when block of text matches certain conditions

22 Jul 2021, 20:24

I can have several files to go through and sometimes I need to insert lines if it matches certain conditions.
I want to insert line Paulie: paid 0 before *** Invoice Paid *** blah blah blah line in both sections of the example below

Input Example:
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
*** Invoice Paid *** blah blah blah

Desired Output:
---------------------------------------------------------------------------------------
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Paulie: paid 0
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
Paulie: paid 0
*** Invoice Paid *** blah blah blah
-------------------------------------------------------------------------------------
I've got the regexs for finding both parts
RegExMatch(aFileContents,"`am)Paid to Paulie \[.*\]\r\n^.*\: payment\r\nGoods returned to store.*\r\n^\*\*\* Invoice Paid \*\*\*", outputvar)
RegExMatch(aFileContents,"`am)Paid to Paulie \[.*\]\r\n^.*\: payment\r\n^\*\*\* Invoice Paid \*\*\*", outputvar2)
I'm unsure how to cycle through the many lines of code and insert the desired line where necessary, any help appreciated, and I'll continue to see if I can make progress myself meanwhile.
User avatar
mikeyww
Posts: 26601
Joined: 09 Sep 2014, 18:38

Re: Inserting a line when block of text matches certain conditions

22 Jul 2021, 21:32

I imagine that you could just use StrReplace for the entire string. It's fast & simple.
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Re: Inserting a line when block of text matches certain conditions

22 Jul 2021, 21:47

I don't know if this is the best way, but put together a solution from the searches I made, specifically st_insertLine from tidbit's string functions library helped
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=53

Code: Select all

FileRead, aFileContents, E:\test\p.txt
outputFile = E:\test\output.txt
FileDelete %outputFile% 
/*
insertLine
   Insert a line of text at the specified line number.
   The line you specify is pushed down 1 and your text is inserted at its
   position. A "line" can be determined by the delimiter parameter. Not
   necessarily just a `r or `n. But perhaps you want a | as your "line".

   insert  = Text you want to insert.
   into    = The text you want to insert into.
   line    = What line number to insert at. Use a 0 or negative to start
             inserting from the end.
   delim   = The string which defines a "line".
   exclude = The text you want to ignore when defining a line.

example: st_insertLine("bbb", "aaa|ccc|ddd", 2, "|")
output:  aaa|bbb|ccc|ddd
*/
RegExMatch(aFileContents,"`am)Paid to Paulie \[.*\]\r\n^.*\: payment\r\nGoods returned to store.*\r\n^\*\*\* Invoice Paid \*\*\*", outputvar)
str_replacement := st_insertLine("Paulie: paid 0", outputvar,3, "`r")
aFileContents := strreplace(aFileContents,outputvar, str_replacement)
RegExMatch(aFileContents,"`am)Paid to Paulie \[.*\]\r\n^.*\: payment\r\n^\*\*\* Invoice Paid \*\*\*", outputvar)
str_replacement := st_insertLine("Paulie: paid 0", outputvar,3, "`r")
aFileContents := strreplace(aFileContents,outputvar, str_replacement)
FileAppend, %aFileContents%, %outputFile% 
st_insertLine(insert, into, line, delim="`n", exclude="`r")
{
   StringReplace, into, into, %delim%, %delim%, UseErrorLevel
   count:=errorlevel+1

   ; Create any lines that don't exist yet, if the Line is less than the total line count.
   if (line<0 && abs(line)>count)
   {
      loop, % abs(line)-count
         into:=delim into
      line:=1
   }
   if (line==0)
      line:=Count+1
   if (line<0)
      line:=count+line+1
   ; Create any lines that don't exist yet. Otherwise the Insert doesn't work.
   if (count<line)
      loop, % line-count
         into.=delim

   loop, parse, into, %delim%, %exclude%
      new.=((a_index==line) ? insert . delim . A_LoopField . delim : A_LoopField . delim)

   return rtrim(new, delim)
}
sofista
Posts: 645
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: Inserting a line when block of text matches certain conditions

22 Jul 2021, 21:57

Hi: My take

Code: Select all

SampleText := "
(
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
*** Invoice Paid *** blah blah blah
)"

Template := "Paid to Paulie \[.*?payment\R\K"
SampleText := RegExReplace(SampleText, Template, "Paulie: paid 0`n")

MsgBox, % SampleText
return

/* 
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Paulie: paid 0
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
Paulie: paid 0
*** Invoice Paid *** blah blah blah
 */
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Re: Inserting a line when block of text matches certain conditions

23 Jul 2021, 02:19

@sofista
Thanks but it doesn't seem to work, also it needs to check for the existence of the exact conditions I outlined, this code if I'm not mistaken is aimed at inserting Paulie:paid 0 no matter what the subsequent lines are, and the subsequent lines have to be either in the format of 1 or 2. below (text in bold is mandatory.)

1.
Paid to Paulie [any entry here]
another_random-text: payment
*** Invoice Paid *** blah blah blah

2.
Paid to Paulie [90]
random-text: payment
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

And my code doesn't work either as it only replaces first instance of the regular expression match and there could be several matches all with different random text in the associated two templates outlined :(
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Re: Inserting a line when block of text matches certain conditions

23 Jul 2021, 03:20

Patched together a solution, needed to use a while loop and run through each match, again not sure if this is the best way, but it seems to work.

Code: Select all

While	Pos :=	RegExMatch(aFileContents,"`am)Paid to Paulie  \[.*\]\R^.*\: payment\RGoods returned to store .*\R^\*\*\* Invoice Paid \*\*\*", outputvar)
{
	str_replacement := st_insertLine("Paulie: paid 0", outputvar,3, "`n")
StringReplace, aFileContents, aFileContents, %outputvar%, %str_replacement%
	
}	

While	Pos :=	RegExMatch(aFileContents,"`am)Paid to Paulie \[.*\]\R^.*\: payment\R\*\*\* Invoice Paid\*\*\*", outputvar)
{
	str_replacement := st_insertLine("Paulie: paid 0"", outputvar,3, "`n")
StringReplace, aFileContents, aFileContents, %outputvar%, %str_replacement%
	
}	
FileAppend, %aFileContents%, %outputFile% 

st_insertLine(insert, into, line, delim="`n", exclude="`n")
{

   StringReplace, into, into, %delim%, %delim%, UseErrorLevel
   count:=errorlevel+1

   ; Create any lines that don't exist yet, if the Line is less than the total line count.
   if (line<0 && abs(line)>count)
   {
      loop, % abs(line)-count
         into:=delim into
      line:=1
   }
   if (line==0)
      line:=Count+1
   if (line<0)
      line:=count+line+1
   ; Create any lines that don't exist yet. Otherwise the Insert doesn't work.
   if (count<line)
      loop, % line-count
         into.=delim

   loop, parse, into, %delim%, %exclude%
      new.=((a_index==line) ? insert . delim . A_LoopField . delim : A_LoopField . delim)

   return rtrim(new, delim)
}
[Mod edit: [code][/code] tags added.]
Last edited by gregster on 23 Jul 2021, 03:53, edited 1 time in total.
Reason: Please use [code] tags. Thank you!
sofista
Posts: 645
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: Inserting a line when block of text matches certain conditions

23 Jul 2021, 07:43

bazkeys wrote:
23 Jul 2021, 02:19
@sofista
Thanks but it doesn't seem to work, also it needs to check for the existence of the exact conditions I outlined, this code if I'm not mistaken is aimed at inserting Paulie:paid 0 no matter what the subsequent lines are, and the subsequent lines have to be either in the format of 1 or 2. below (text in bold is mandatory.)
I see, it seems that I misread your post :oops: Well, pursuing the same idea, a positive look-ahead can deal with the subsequent lines

Code: Select all

Template := "Paid to Paulie \[.*?payment\R\K(?=(Goods returned to store.*?\R)?\Q*** Invoice Paid ***\E)"
SampleText := RegExReplace(SampleText, Template, "Paulie: paid 0`n")
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Re: Inserting a line when block of text matches certain conditions

23 Jul 2021, 19:32

@sofista
No worries, I appreciate the help anyway. Also I could have given a deeper explanation of the requirements, but tried to keep the explanation as brief as possible, in hindsight maybe it would have been better If I had make everything clear, though I keep finding exceptions that I need to adapt the code for.
On the last one, I ran it, it kind of works, but it needs tweaking, like my own effort does for some further exceptions.

One exception is that there is the possibility of a few further intervening lines in the text that I need to look up. So basically each template match can search until a line break(blank line, carriage return etc), remember the actual file could be big with lots of similar patterns for each, if there is a line break it is a new entity.

So
SampleText := "
(
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
occasionally there is some random text here
less occasionally even more random text
random-text: payment
yet more infrequent random text
Goods returned to store blah blah blah
and more more infrequent random text
who knows, could even be a second , third line or more
*** Invoice Paid *** blah blah blah
eventually there will be a blank line, carriage return etc and the pattern matching can start again on the next block of text

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
occasionally there is some random text here
less occasionally even more random text
another_random-text: payment
yet more infrequent random text
and more more infrequent random text
who knows, could even be a second , third line or more
*** Invoice Paid *** blah blah blahblank line coming up

and so on and so on
)"

As I am struggling with regex, I tried to figure out what your code was exactly doing, but still not quite sure.
I try to do some tests of the regex in https://regex101.com/, but it doesn't seem to work with all autohotkey reg ex patterns, is there one more suitable for autohotkey testing?
sofista
Posts: 645
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: Inserting a line when block of text matches certain conditions

24 Jul 2021, 09:04

bazkeys wrote:
23 Jul 2021, 19:32
@sofista
No worries, I appreciate the help anyway. Also I could have given a deeper explanation of the requirements, but tried to keep the explanation as brief as possible, in hindsight maybe it would have been better If I had make everything clear, though I keep finding exceptions that I need to adapt the code for.
On the last one, I ran it, it kind of works, but it needs tweaking, like my own effort does for some further exceptions.

One exception is that there is the possibility of a few further intervening lines in the text that I need to look up. So basically each template match can search until a line break(blank line, carriage return etc), remember the actual file could be big with lots of similar patterns for each, if there is a line break it is a new entity.
No problem, here I go again. This new regular expression checks the three conditions that seems to me to be mandatory (let me know if this is not the case) :

1) "Paid to Paulie \[" is at the start of a line, then
2) "payment" is at the end of another line, and finally
3) "*** Invoice Paid ***" is at the start of a further line

Only if the three conditions are meet, "Paulie: paid 0" is inserted just before 3) in its own line. My regex worked fine in tests against the four examples you provided:

Code: Select all

SampleText := "
(
some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Goods returned to store blah blah blah
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
*** Invoice Paid *** blah blah blah

some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
occasionally there is some random text here
less occasionally even more random text
random-text: payment
yet more infrequent random text
Goods returned to store blah blah blah
and more more infrequent random text
who knows, could even be a second , third line or more
*** Invoice Paid *** blah blah blah
eventually there will be a blank line, carriage return etc and the pattern matching can start again on the next block of text

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
occasionally there is some random text here
less occasionally even more random text
another_random-text: payment
yet more infrequent random text
and more more infrequent random text
who knows, could even be a second , third line or more
*** Invoice Paid *** blah blah blahblank line coming up

and so on and so on
)"

Template := "(?<=\v)Paid to Paulie \[.*?payment\R.*?\K(?=(?<=\v)\*{3} Invoice Paid \*{3})"
SampleText := RegExReplace(SampleText, Template, "Paulie: paid 0`n")

MsgBox, % SampleText
return

/* Output:

some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
random-text: payment
Goods returned to store blah blah blah
Paulie: paid 0
*** Invoice Paid *** blah blah blah

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
another_random-text: payment
Paulie: paid 0
*** Invoice Paid *** blah blah blah

some random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [90]
occasionally there is some random text here
less occasionally even more random text
random-text: payment
yet more infrequent random text
Goods returned to store blah blah blah
and more more infrequent random text
who knows, could even be a second , third line or more
Paulie: paid 0
*** Invoice Paid *** blah blah blah
eventually there will be a blank line, carriage return etc and the pattern matching can start again on the next block of text

yet another random unimportant text
more random unimportant text and could have several until next line example
Paid to Paulie [full]
occasionally there is some random text here
less occasionally even more random text
another_random-text: payment
yet more infrequent random text
and more more infrequent random text
who knows, could even be a second , third line or more
Paulie: paid 0
*** Invoice Paid *** blah blah blahblank line coming up

and so on and so on
 */
bazkeys wrote:
23 Jul 2021, 19:32
As I am struggling with regex, I tried to figure out what your code was exactly doing, but still not quite sure.
I try to do some tests of the regex in https://regex101.com/, but it doesn't seem to work with all autohotkey reg ex patterns, is there one more suitable for autohotkey testing?
Can't say anything about this, as I don't use regex101 nor any other service of that flair, just Notepad++ as an editor.
bazkeys
Posts: 98
Joined: 20 Jan 2021, 21:58

Re: Inserting a line when block of text matches certain conditions

24 Jul 2021, 20:46

@sofista
Thanks again. I haven't checked your code yey. I'll try to do shortly.
Truth is Regex is breaking my heart, sometimes I think I'm getting it, but soon after that feel confused as hell again.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: JoeWinograd, yabab33299 and 115 guests