Replacement tags when first tag empty...
Posted: Fri Dec 09, 2005 11:09 am
Hi,
I had a big code conversion job to do, and it required TP's regexp, so I decided to write a wee tutorial for the others in my office. Sadly, it didn't turn out as I expected it to.
Basically...
My search expression matches two groups. The first group may or may not be matched.
My replacement expression disregards first match completely, and sticks the second match onto the end of some plain text.
In the case where the first match is not fulfilled, the second match gets shifted to the first, thus completely destroying my replacement expression!
Does anyone know of a workaround for this? It makes sense that it would happen, but I'd really hoped it wouldn't.
Here's a full copy of my 'tutorial', comments and criticisms on it, if you're willing...
Thanks in advance, I'll not be so bold as to offer $25 for an answer! (some people eh?)
Task:
Replace all references to the public final statics contained within myContainer
(across all files) with defines
Problem:
The statics can be referenced from within the class, outside the class
through the uninstantiated object, outside the class by referencing an
instatiated myContainer object, outside the class by using an IQ
function that returns the global instance of the class (ie: getContainer())
Constructing the Search Expression:
1. Match all vars/functions using a character class: [A-Za-z0-9_]+
2. Lock this character class to the ends of words using the <> characters: \<[A-Za-z0-9_]+\>
3. Account for the brackets used in functions, making it a 0 or more match: [\(\)]*
4. Putting 2 + 3 together: \<[A-Za-z0-9_]+\>[\(\)]*
5. Make the match require a period immediately after the var/function match:
\<[A-Za-z0-9_]+\>[\(\)]*\.
6. Group this match together so we can make it a zero or more match. This will
allow the full regexp to match the single usage of the vars as well as the
Object.member style reference:
\(\<[A-Za-z0-9_]+\>[\(\)]*\.\)*
7. Use the (thingone|thingtwo) (brackets and pipe must be escaped) functionality to
match all the vars:
\(kState_Game\|kState_Attract\|kState_Max\|kCat_Nil\|kCat_Nor\|kCat_For\|kCat_Adv\|kCat_Ers\|kCat_Max\|kRSt_Nor\|kRSt_Erase\|kRSt_EraseEffect\|kRSt_Wait\)
8. Combine match 6 with match 7 to create the full regular expression
\(\<[A-Za-z0-9_]+\>[\(\)]*\.\)*\(kState_Game\|kState_Attract\|kState_Max\|kCat_Nil\|kCat_Nor\|kCat_For\|kCat_Adv\|kCat_Ers\|kCat_Max\|kRSt_Nor\|kRSt_Erase\|kRSt_EraseEffect\|kRSt_Wait\)
Test the above regexp on the test strings below. Strings referencing the members via
objects will match twice, but this doesn't matter as we'll be using a replacement
expression to do the actual work. This means that as soon as one string is matched
and replaced, the second match is removed.
Constructing the Replacement Expression:
We need access to the name of the member variable we're catching, and we use the match
tags to do this (\1 \2 \x...). These match tags contain the text matched by the groups
in your search expression. Groups are defined by brackets, and we have two groups.
The first is the object match, the second is the variable match.
Replacement expression: CONTAINER_\2
Select the test pieces below and test the expression.
PROBLEM:
The member vars that are referenced without object name are replaced with 'CONTAINER_\2',
showing that the \1 contains what I had hoped would be \2.
Test Pieces:
// a member we don't want to match
weDONTmatchTHIS
// list of members we DO want to match
kState_Game
kState_Attract
kState_Max
kCat_Nil
kCat_Nor
kCat_For
kCat_Adv
kCat_Ers
kCat_Max
kRSt_Nor
kRSt_Erase
kRSt_EraseEffect
kRSt_Wait
// different usages
myContainer.weDONTmatchTHIS
myContainer.kState_Game
myContainer.kState_Attract
myContainer.kState_Max
myContainer.kCat_Nil
myContainer.kCat_Nor
myContainer.kCat_For
myContainer.kCat_Adv
myContainer.kCat_Ers
myContainer.kCat_Max
myContainer.kRSt_Nor
myContainer.kRSt_Erase
myContainer.kRSt_EraseEffect
myContainer.kRSt_Wait
getContainer().weDONTmatchTHIS
getContainer().kState_Game
getContainer().kState_Attract
getContainer().kState_Max
getContainer().kCat_Nil
getContainer().kCat_Nor
getContainer().kCat_For
getContainer().kCat_Adv
getContainer().kCat_Ers
getContainer().kCat_Max
getContainer().kRSt_Nor
getContainer().kRSt_Erase
getContainer().kRSt_EraseEffect
getContainer().kRSt_Wait
I had a big code conversion job to do, and it required TP's regexp, so I decided to write a wee tutorial for the others in my office. Sadly, it didn't turn out as I expected it to.
Basically...
My search expression matches two groups. The first group may or may not be matched.
My replacement expression disregards first match completely, and sticks the second match onto the end of some plain text.
In the case where the first match is not fulfilled, the second match gets shifted to the first, thus completely destroying my replacement expression!
Does anyone know of a workaround for this? It makes sense that it would happen, but I'd really hoped it wouldn't.
Here's a full copy of my 'tutorial', comments and criticisms on it, if you're willing...
Thanks in advance, I'll not be so bold as to offer $25 for an answer! (some people eh?)
Task:
Replace all references to the public final statics contained within myContainer
(across all files) with defines
Problem:
The statics can be referenced from within the class, outside the class
through the uninstantiated object, outside the class by referencing an
instatiated myContainer object, outside the class by using an IQ
function that returns the global instance of the class (ie: getContainer())
Constructing the Search Expression:
1. Match all vars/functions using a character class: [A-Za-z0-9_]+
2. Lock this character class to the ends of words using the <> characters: \<[A-Za-z0-9_]+\>
3. Account for the brackets used in functions, making it a 0 or more match: [\(\)]*
4. Putting 2 + 3 together: \<[A-Za-z0-9_]+\>[\(\)]*
5. Make the match require a period immediately after the var/function match:
\<[A-Za-z0-9_]+\>[\(\)]*\.
6. Group this match together so we can make it a zero or more match. This will
allow the full regexp to match the single usage of the vars as well as the
Object.member style reference:
\(\<[A-Za-z0-9_]+\>[\(\)]*\.\)*
7. Use the (thingone|thingtwo) (brackets and pipe must be escaped) functionality to
match all the vars:
\(kState_Game\|kState_Attract\|kState_Max\|kCat_Nil\|kCat_Nor\|kCat_For\|kCat_Adv\|kCat_Ers\|kCat_Max\|kRSt_Nor\|kRSt_Erase\|kRSt_EraseEffect\|kRSt_Wait\)
8. Combine match 6 with match 7 to create the full regular expression
\(\<[A-Za-z0-9_]+\>[\(\)]*\.\)*\(kState_Game\|kState_Attract\|kState_Max\|kCat_Nil\|kCat_Nor\|kCat_For\|kCat_Adv\|kCat_Ers\|kCat_Max\|kRSt_Nor\|kRSt_Erase\|kRSt_EraseEffect\|kRSt_Wait\)
Test the above regexp on the test strings below. Strings referencing the members via
objects will match twice, but this doesn't matter as we'll be using a replacement
expression to do the actual work. This means that as soon as one string is matched
and replaced, the second match is removed.
Constructing the Replacement Expression:
We need access to the name of the member variable we're catching, and we use the match
tags to do this (\1 \2 \x...). These match tags contain the text matched by the groups
in your search expression. Groups are defined by brackets, and we have two groups.
The first is the object match, the second is the variable match.
Replacement expression: CONTAINER_\2
Select the test pieces below and test the expression.
PROBLEM:
The member vars that are referenced without object name are replaced with 'CONTAINER_\2',
showing that the \1 contains what I had hoped would be \2.
Test Pieces:
// a member we don't want to match
weDONTmatchTHIS
// list of members we DO want to match
kState_Game
kState_Attract
kState_Max
kCat_Nil
kCat_Nor
kCat_For
kCat_Adv
kCat_Ers
kCat_Max
kRSt_Nor
kRSt_Erase
kRSt_EraseEffect
kRSt_Wait
// different usages
myContainer.weDONTmatchTHIS
myContainer.kState_Game
myContainer.kState_Attract
myContainer.kState_Max
myContainer.kCat_Nil
myContainer.kCat_Nor
myContainer.kCat_For
myContainer.kCat_Adv
myContainer.kCat_Ers
myContainer.kCat_Max
myContainer.kRSt_Nor
myContainer.kRSt_Erase
myContainer.kRSt_EraseEffect
myContainer.kRSt_Wait
getContainer().weDONTmatchTHIS
getContainer().kState_Game
getContainer().kState_Attract
getContainer().kState_Max
getContainer().kCat_Nil
getContainer().kCat_Nor
getContainer().kCat_For
getContainer().kCat_Adv
getContainer().kCat_Ers
getContainer().kCat_Max
getContainer().kRSt_Nor
getContainer().kRSt_Erase
getContainer().kRSt_EraseEffect
getContainer().kRSt_Wait