Rydygier 1309 Posted November 15, 2014 (edited) From time to time I have massive code to update with hundreds of lines needing attention. For example I need to replace all _array set [(count _array),_var] with _array pushBack _var. Common find&replace all can't handle such cases. Is there any SQF editor allowing me to do it easy way via find&replace using wildcards? Like this: _array1 set [(count _array1),_val1]; 1. set [(count *), replace with: pushBack result: _array1 pushBack _val1]; 2. pushBack *] replace with: pushBack * result: _array1 pushBack _val1; And voila. Hours of most tedious work in 30 seconds. If nothing like that out there, I would like to request such feature... Edited November 15, 2014 by Rydygier Share this post Link to post Share on other sites
A.Cyprus 16 Posted November 15, 2014 I use notepad++, purely because I'm familiar with it from past projects. While it isn't an SQF editor as such, you can load up syntax highlighting from various sources and it supports regex search and replace, along with 'replace all', 'replace in all open documents' and 'replace only in selection' features. Share this post Link to post Share on other sites
Rydygier 1309 Posted November 15, 2014 (edited) And I even have it. So, tried above operation for notepad++, but apparently it doesn't recognize * as a wildcard and looks for * in the code. Is n++ using other symbols for wildcards or it's after all unable to perform, what I described? Yeah, beeing accustomed to one editor is strong anchor that can make you using it for years despite it's flaws and better alternatives. For example solely for that reason I'm still using AEdit for regular scripting. Otherwise I would long time ago look for another tool because of not updated syntax highlighting and ineffective loading of big files. But, if another editor could provide me said feature, I would seriously consider a change. Frankly, I started to wonder, if not to try make a script doing such operations on provided strings, but even if possible, I preffer leave it as secondary option. Edited November 15, 2014 by Rydygier Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 I use PHPStorm but any text editor that supports Regular Expressions will do. Notepad++ also seems to support them: http://blog.creativeitp.com/posts-and-articles/editors/understanding-regex-with-notepad/ http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/ They can be tricky to get the hang of so if you feel you need any help, let me know Share this post Link to post Share on other sites
Rydygier 1309 Posted November 15, 2014 Cool, thanks. I'll study this. :) Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 Good luck :) I went and found another link as I noticed the Understanding regex-page was a bit bare. On the lefthand side you'll see all the subjects when it comes to writing these babies: http://www.regular-expressions.info/tutorial.html Share this post Link to post Share on other sites
A.Cyprus 16 Posted November 15, 2014 In notepad++, do CTRL+H, then: Find what: (_array\d) .*(val\d)]; Replace with: \1 pushBack \2; Check the following options: - wrap around - regular expression Hit 'Replace All' You may need to adjust the search term if it needs to be more specific to just the lines you want. Make a backup of your script before running and maybe test step by step using 'Replace' first. Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 If I may add a bit to your expression: (_array\d) .*(val\d)]; would work better like this: (_array\d+) .*(val\d+)]; Otherwise it'd only match for single digits (_array1 would match but _array10 wouldn't). Share this post Link to post Share on other sites
Rydygier 1309 Posted November 15, 2014 Thanks, but _array and _val was just exemplary. Thing is, name of the array and value may be any (local variable). If I understood correctly, your example will find only where exactly "_array" and "val" appear. I mostly need regex code meaning "any chain of any symbols here" to cover variables of any name. As said, I'll study this regex, so probably sooner or later I'll find, if possible, such code, but if you or anyone know it already, fell free to share with me. :) Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 If you can give a few examples of what you need to replace exactly I can probably write one up for you. Also, consider using multiple patterns just to keep things manageable for yourself. RegExes are a very powerful thing but when you try to have one that does too many things it just becomes confusing (at least for my brain). But it's very well possible to have a pattern that matches more generic variable names as long as there's something in the expression that never changes, like a function name for example. Share this post Link to post Share on other sites
Rydygier 1309 Posted November 15, 2014 (edited) If you can give a few examples of what you need to replace exactly I can probably write one up for you. Sure, but that's just one example. I seek for universal knowledge for future uses, not just change certain portion of code. Example, I already done manually - to turn this: if (_SpecForcheck) then {if not (_vh in _EnSpecFor) then {_EnSpecFor set [(count _EnSpecFor),_vh]};if not (_grp in _EnSpecForG) then {_EnSpecForG set [(count _EnSpecForG),_grp]}}; if (_reconcheck) then {if not (_vh in _Enrecon) then {_Enrecon set [(count _Enrecon),_vh]};if not (_grp in _EnreconG) then {_EnreconG set [(count _EnreconG),_grp]}}; if (_FOcheck) then {if not (_vh in _EnFO) then {_EnFO set [(count _EnFO),_vh]};if not (_grp in _EnFOG) then {_EnFOG set [(count _EnFOG),_grp]}}; if (_sniperscheck) then {if not (_vh in _Ensnipers) then {_Ensnipers set [(count _Ensnipers),_vh]};if not (_grp in _EnsnipersG) then {_EnsnipersG set [(count _EnsnipersG),_grp]}}; if (_ATinfcheck) then {if not (_vh in _EnATinf) then {_EnATinf set [(count _EnATinf),_vh]};if not (_grp in _EnATinfG) then {_EnATinfG set [(count _EnATinfG),_grp]}}; if (_AAinfcheck) then {if not (_vh in _EnAAinf) then {_EnAAinf set [(count _EnAAinf),_vh]};if not (_grp in _EnAAinfG) then {_EnAAinfG set [(count _EnAAinfG),_grp]}}; if (_Infcheck) then {if not (_vh in _EnInf) then {_EValue = _EValue + 1;_EnInf set [(count _EnInf),_vh]};if not (_grp in _EnInfG) then {_EnInfG set [(count _EnInfG),_grp]}}; if (_Artcheck) then {if not (_vh in _EnArt) then {_EValue = _EValue + 3;_EnArt set [(count _EnArt),_vh]};if not (_grp in _EnArtG) then {_EnArtG set [(count _EnArtG),_grp]}}; if (_HArmorcheck) then {if not (_vh in _EnHArmor) then {_EValue = _EValue + 10;_EnHArmor set [(count _EnHArmor),_vh]};if not (_grp in _EnHArmorG) then {_EnHArmorG set [(count _EnHArmorG),_grp]}}; if (_MArmorcheck) then {if not (_vh in _EnMArmor) then {_EnMArmor set [(count _EnMArmor),_vh]};if not (_grp in _EnMArmorG) then {_EnMArmorG set [(count _EnMArmorG),_grp]}}; if (_LArmorcheck) then {if not (_vh in _EnLArmor) then {_EValue = _EValue + 5;_EnLArmor set [(count _EnLArmor),_vh]};if not (_grp in _EnLArmorG) then {_EnLArmorG set [(count _EnLArmorG),_grp]}}; if (_LArmorATcheck) then {if not (_vh in _EnLArmorAT) then {_EnLArmorAT set [(count _EnLArmorAT),_vh]};if not (_grp in _EnLArmorATG) then {_EnLArmorATG set [(count _EnLArmorATG),_grp]}}; if (_Carscheck) then {if not (_vh in _EnCars) then {_EValue = _EValue + 3;_EnCars set [(count _EnCars),_vh]};if not (_grp in _EnCarsG) then {_EnCarsG set [(count _EnCarsG),_grp]}}; if (_Aircheck) then {if not (_vh in _EnAir) then {_EValue = _EValue + 15;_EnAir set [(count _EnAir),_vh]};if not (_grp in _EnAirG) then {_EnAirG set [(count _EnAirG),_grp]}}; if (_BAircheck) then {if not (_vh in _EnBAir) then {_EnBAir set [(count _EnBAir),_vh]};if not (_grp in _EnBAirG) then {_EnBAirG set [(count _EnBAirG),_grp]}}; if (_RAircheck) then {if not (_vh in _EnRAir) then {_EnRAir set [(count _EnRAir),_vh]};if not (_grp in _EnRAirG) then {_EnRAirG set [(count _EnRAirG),_grp]}}; if (_NCAircheck) then {if not (_vh in _EnNCAir) then {_EnNCAir set [(count _EnNCAir),_vh]};if not (_grp in _EnNCAirG) then {_EnNCAirG set [(count _EnNCAirG),_grp]}}; if (_Navalcheck) then {if not (_vh in _EnNaval) then {_EnNaval set [(count _EnNaval),_vh]};if not (_grp in _EnNavalG) then {_EnNavalG set [(count _EnNavalG),_grp]}}; if (_Staticcheck) then {if not (_vh in _EnStatic) then {_EValue = _EValue + 1;_EnStatic set [(count _EnStatic),_vh]};if not (_grp in _EnStaticG) then {_EnStaticG set [(count _EnStaticG),_grp]}}; if (_StaticAAcheck) then {if not (_vh in _EnStaticAA) then {_EnStaticAA set [(count _EnStaticAA),_vh]};if not (_grp in _EnStaticAAG) then {_EnStaticAAG set [(count _EnStaticAAG),_grp]}}; if (_StaticATcheck) then {if not (_vh in _EnStaticAT) then {_EnStaticAT set [(count _EnStaticAT),_vh]};if not (_grp in _EnStaticATG) then {_EnStaticATG set [(count _EnStaticATG),_grp]}}; if (_Supportcheck) then {if not (_vh in _EnSupport) then {_EnSupport set [(count _EnSupport),_vh]};if not (_grp in _EnSupportG) then {_EnSupportG set [(count _EnSupportG),_grp]}}; if (_Cargocheck) then {if not (_vh in _EnCargo) then {_EnCargo set [(count _EnCargo),_vh]};if not (_grp in _EnCargoG) then {_EnCargoG set [(count _EnCargoG),_grp]}}; if (_NCCargocheck) then {if not (_vh in _EnNCCargo) then {_EnNCCargo set [(count _EnNCCargo),_vh]};if not (_grp in _EnNCCargoG) then {_EnNCCargoG set [(count _EnNCCargoG),_grp]}}; if (_Crewcheck) then {if not (_vh in _EnCrew) then {_EnCrew set [(count _EnCrew),_vh]};if not (_grp in _EnCrewG) then {_EnCrewG set [(count _EnCrewG),_grp]}}; if (_NCrewInfcheck) then {if not (_vh in _EnNCrewInf) then {_EnNCrewInf set [(count _EnNCrewInf),_vh]};if not (_grp in _EnNCrewInfG) then {_EnNCrewInfG set [(count _EnNCrewInfG),_grp]}}; into: if (_SpecForcheck) then {if not (_vh in _EnSpecFor) then {_EnSpecFor pushBack _vh};if not (_grp in _EnSpecForG) then {_EnSpecForG pushBack _grp}}; if (_reconcheck) then {if not (_vh in _Enrecon) then {_Enrecon pushBack _vh};if not (_grp in _EnreconG) then {_EnreconG pushBack _grp}}; if (_FOcheck) then {if not (_vh in _EnFO) then {_EnFO pushBack _vh};if not (_grp in _EnFOG) then {_EnFOG pushBack _grp}}; if (_sniperscheck) then {if not (_vh in _Ensnipers) then {_Ensnipers pushBack _vh};if not (_grp in _EnsnipersG) then {_EnsnipersG pushBack _grp}}; if (_ATinfcheck) then {if not (_vh in _EnATinf) then {_EnATinf pushBack _vh};if not (_grp in _EnATinfG) then {_EnATinfG pushBack _grp}}; if (_AAinfcheck) then {if not (_vh in _EnAAinf) then {_EnAAinf pushBack _vh};if not (_grp in _EnAAinfG) then {_EnAAinfG pushBack _grp}}; if (_Infcheck) then {if not (_vh in _EnInf) then {_EValue = _EValue + 1;_EnInf pushBack _vh};if not (_grp in _EnInfG) then {_EnInfG pushBack _grp}}; if (_Artcheck) then {if not (_vh in _EnArt) then {_EValue = _EValue + 3;_EnArt pushBack _vh};if not (_grp in _EnArtG) then {_EnArtG pushBack _grp}}; if (_HArmorcheck) then {if not (_vh in _EnHArmor) then {_EValue = _EValue + 10;_EnHArmor pushBack _vh};if not (_grp in _EnHArmorG) then {_EnHArmorG pushBack _grp}}; if (_MArmorcheck) then {if not (_vh in _EnMArmor) then {_EnMArmor pushBack _vh};if not (_grp in _EnMArmorG) then {_EnMArmorG pushBack _grp}}; if (_LArmorcheck) then {if not (_vh in _EnLArmor) then {_EValue = _EValue + 5;_EnLArmor pushBack _vh};if not (_grp in _EnLArmorG) then {_EnLArmorG pushBack _grp}}; if (_LArmorATcheck) then {if not (_vh in _EnLArmorAT) then {_EnLArmorAT pushBack _vh};if not (_grp in _EnLArmorATG) then {_EnLArmorATG pushBack _grp}}; if (_Carscheck) then {if not (_vh in _EnCars) then {_EValue = _EValue + 3;_EnCars pushBack _vh};if not (_grp in _EnCarsG) then {_EnCarsG pushBack _grp}}; if (_Aircheck) then {if not (_vh in _EnAir) then {_EValue = _EValue + 15;_EnAir pushBack _vh};if not (_grp in _EnAirG) then {_EnAirG pushBack _grp}}; if (_BAircheck) then {if not (_vh in _EnBAir) then {_EnBAir pushBack _vh};if not (_grp in _EnBAirG) then {_EnBAirG pushBack _grp}}; if (_RAircheck) then {if not (_vh in _EnRAir) then {_EnRAir pushBack _vh};if not (_grp in _EnRAirG) then {_EnRAirG pushBack _grp}}; if (_NCAircheck) then {if not (_vh in _EnNCAir) then {_EnNCAir pushBack _vh};if not (_grp in _EnNCAirG) then {_EnNCAirG pushBack _grp}}; if (_Navalcheck) then {if not (_vh in _EnNaval) then {_EnNaval pushBack _vh};if not (_grp in _EnNavalG) then {_EnNavalG pushBack _grp}}; if (_Staticcheck) then {if not (_vh in _EnStatic) then {_EValue = _EValue + 1;_EnStatic pushBack _vh};if not (_grp in _EnStaticG) then {_EnStaticG pushBack _grp}}; if (_StaticAAcheck) then {if not (_vh in _EnStaticAA) then {_EnStaticAA pushBack _vh};if not (_grp in _EnStaticAAG) then {_EnStaticAAG pushBack _grp}}; if (_StaticATcheck) then {if not (_vh in _EnStaticAT) then {_EnStaticAT pushBack _vh};if not (_grp in _EnStaticATG) then {_EnStaticATG pushBack _grp}}; if (_Supportcheck) then {if not (_vh in _EnSupport) then {_EnSupport pushBack _vh};if not (_grp in _EnSupportG) then {_EnSupportG pushBack _grp}}; if (_Cargocheck) then {if not (_vh in _EnCargo) then {_EnCargo pushBack _vh};if not (_grp in _EnCargoG) then {_EnCargoG pushBack _grp}}; if (_NCCargocheck) then {if not (_vh in _EnNCCargo) then {_EnNCCargo pushBack _vh};if not (_grp in _EnNCCargoG) then {_EnNCCargoG pushBack _grp}}; if (_Crewcheck) then {if not (_vh in _EnCrew) then {_EnCrew pushBack _vh};if not (_grp in _EnCrewG) then {_EnCrewG pushBack _grp}}; if (_NCrewInfcheck) then {if not (_vh in _EnNCrewInf) then {_EnNCrewInf pushBack _vh};if not (_grp in _EnNCrewInfG) then {_EnNCrewInfG pushBack _grp}}; As you can see, each array here has different name (each here start with _En, but it's only here that way. Name of the array may be really any), and there are two possible names for value to put into each array (and again, only here. This name also can be any). Also, consider using multiple patterns just to keep things manageable for yourself. RegExes are a very powerful thing but when you try to have one that does too many things it just becomes confusing (at least for my brain). Hmm. If regex equivalent of old, good, single asterisk symbol wildcard is so complex or not possible, then maybe it's not good way to follow for me? I need universal solution applicable in any situation. Just as * would work for me in the first post. Edited November 15, 2014 by Rydygier Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 (edited) Hmm. If regex equivalent of old, good, single asterisk symbol wildcard is so complex, then maybe it's not good way to follow? I need universal solution applicable in any situation. Just as * would work for me. I respectfully disagree but I understand regexes are overwhelming at first. They are as universal as it gets though and are the tool for the job you want to do :). Give me a few seconds to write up the pattern for the example you posted. I'll give an explanation of what it does and why. ---------- Post added at 15:03 ---------- Previous post was at 14:36 ---------- Alright, done. Using this string as an example: if (_SpecForcheck) then {if not (_vh in _EnSpecFor) then {_EnSpecFor set [(count _EnSpecFor),_vh]};if not (_grp in _EnSpecForG) then {_EnSpecForG set [(count _EnSpecForG),_grp]}}; The following pattern: ([_]\w+)[\s]set[\s][\[][\(]count\s[_]\w+[\)],([_]\w+)[\]] Will match this part: _EnSpecFor set [(count _EnSpecFor),_vh] And replacing the above match with: \1 pushBack \2 Turns the example string into: if (_SpecForcheck) then {if not (_vh in _EnSpecFor) then {_EnSpecFor pushBack _vh};if not (_grp in _EnSpecForG) then {_EnSpecForG pushBack _grp}}; I'll explain each part of the pattern: ([_]\w+)[\s]set[\s][\[][\(]count\s[_]\w+[\)],([_]\w+)[\]] This part: ([_]\w+) Matches _EnSpecFor The ( and ) make it a 'matching group' meaning you can reference any text it matches. Since this is the first matching group in the expression (it's at the start of the pattern), you reference it by \1 in the replacement string. The [_] part matches the underscore while \w+ is a shorthand notation for matching letters (upper and lowercase) and numbers. The + behind \w indicates that the pattern needs to appear 1 or more times, the RegEx.info site I linked you to has an explanation of all that. Next up in the pattern is [\s] which matches a single space. I don't have ( and ) around it because it's not something you need to reference in the replacement string. After that comes set which I just typed out as a string, no need to capture it as a match either since it's not used in the replacement string. Another [\s] and then comes this abomination: [\[]. As you may have noticed, some characters have special meaning in a RegEx pattern, the [ and ] indicate a matching block of one or more characters. Since Arma uses [ and ] for array notations, I escaped the [ symbol by putting a \ in front of it. The same goes for the [\(] that comes directly after it. The ( needs to be escaped because it would otherwise indicate the start of a matching group. -edit Forgot to mention the word count. It's just typed out as it's another thing we don't need to match. Another \s to account for the space followed by an [_] for the underscore of the variable name and \w+ for the rest of the variable name. I did not put ( and ) around the underscore-variable name part this time because we already captured that with our first matching group. We then have [\)] to match the closing part followed by a ,. After this comes our second matching group: ([_]\w+). As you can see, this follows the same pattern as the one in our first matching group but since the pattern is written for the entire string, it will match _vh instead of _EnSpecFor. -edit: Since we already have a matching group defined, we can reference this one in the replacement string as \2. If you'd add a third matching group that'd be \3 and so-on. We close off the pattern with [\]] which matches the closing blockhook in your code. I hope the above makes sense, feel free to ask me anything you want to know about these evil things :) Edited November 15, 2014 by BadLuckBurt Share this post Link to post Share on other sites
A.Cyprus 16 Posted November 15, 2014 Just checking this thread after a hearty lunch, and looks like it's all sorted. Nice one BadLuckBurt, good regex. It's what I meant earlier when I said you may need to make it more specific, (I was rushing my reply as I was on mobile at the time :D lazy me!) Good luck, Rydygier :) Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 Nice one BadLuckBurt, good regex. It's what I meant earlier when I said you may need to make it more specific, (I was rushing my reply as I was on mobile at the time :D lazy me!) Thanks :) I learnt them to do url rewrites for websites but I use them for so many things now, including Arma scripting. Share this post Link to post Share on other sites
A.Cyprus 16 Posted November 15, 2014 Lol, same here in fact! Mod_rewrite ftw! Powerful black magic they are, but easily forgotten if you're out of practice. Share this post Link to post Share on other sites
Rydygier 1309 Posted November 15, 2014 Thanks a lot, it's great help. :) Will save me lots of future tedious work. Of course now, when idea pop up, I'm anyway trying to write also sqf doing such things, just for exercise. :) Share this post Link to post Share on other sites
badluckburt 78 Posted November 15, 2014 Glad I could help. Find and replace stuff becomes so easy once you use RegEx, especially for more complex stuff. Share this post Link to post Share on other sites
das attorney 858 Posted November 16, 2014 @BadLuckBurt Thanks for this info. I have used regex in the past for a couple of things, but didn't know it could be this flexible with so much ease. Much appreciated :) Share this post Link to post Share on other sites
badluckburt 78 Posted November 16, 2014 You're welcome :) If you ever need help with one, just shoot me a PM or something. Share this post Link to post Share on other sites