Mat Posted September 6, 2010 Share Posted September 6, 2010 So I decided I needed this, and wrote a nice workaround. Usage is simple:#include "StringRegExpReplaceCallback.au3" $sString = "%48%65%6C%6C%6F%2C%20%77%6F%72%6C%64%21" MsgBox(0, $sString, StringRegExpReplaceCallback($sString, "%([0-9A-f]{2})", "Callback")) Func Callback($asMatches) Return Chr(Dec($asMatches[1])) EndFunc ;==>CallbackHow it worksIt uses StringRegExp with the second option, and passes that array straight to the callback function. It then replaces the match with the return value of the callback by using StringLeft() & StringRight() so that that will be the only replacement made and will be accurate. It then increments the offset so that the same match won't be returned in the next loop.The callback function is passed the array, and returns the replacement value. If it sets the @error flag to non-zero then the function will stop looping.expandcollapse popup; #FUNCTION# ===================================================================================================================== ; Name...........: StringRegExpReplaceCallback ; Description ...: ; Syntax.........: StringRegExpReplaceCallback($sString, $sPattern, $sFunc [, $iLimit ] ) ; Parameters ....: $sString - The input string. ; $sPattern - The regular expression to compare. See StringRegExp for pattern definition characters. ; $sFunc - The name of the user function to call. ; $iLimit - [Optional] The max number of time to call the callback function. Default (zero) is unlimited. ; Return values .: Success - The new string. The number of callbacks done. ; Failure - Will return the original string and set the @error flag. ; Author ........: Mat ; Modified.......: ; Remarks .......: The callback function should have a single argument. This will be an array of matches, with the complete match ; in the first element. ; Related .......: ; Link ..........: http://www.php.net/manual/en/function.preg-replace-callback.php ; Example .......: Yes ; ================================================================================================================================ Func StringRegExpReplaceCallback($sString, $sPattern, $sFunc, $iLimit = 0) Local $iOffset = 1, $iDone = 0, $iMatchOffset While True $aRes = StringRegExp($sString, $sPattern, 2, $iOffset) If @error Then ExitLoop $sRet = Call($sFunc, $aRes) If @error Then Return SetError(@error, $iDone, $sString) $iOffset = StringInStr($sString, $aRes[0], 1, 1, $iOffset) $sString = StringLeft($sString, $iOffset - 1) & $sRet & StringMid($sString, $iOffset + StringLen($aRes[0])) $iOffset += StringLen($sRet) $iDone += 1 If $iDone = $iLimit Then ExitLoop WEnd Return SetExtended($iDone, $sString) EndFunc ;==>StringRegExpReplaceCallbackDownload LinkDownloads so far is shown on the downloads page.Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
MrCreatoR Posted September 6, 2010 Share Posted September 6, 2010 http://www.autoitscript.com/trac/autoit/ticket/588 http://www.autoitscript.com/forum/index.php?showtopic=82292 Spoiler Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1 AutoIt Russian Community My Work... Spoiler Projects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize ProgramUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF Examples: ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating ) * === My topics === * ================================================== ================================================== AutoIt is simple, subtle, elegant. © AutoIt Team Link to comment Share on other sites More sharing options...
Mat Posted September 6, 2010 Author Share Posted September 6, 2010 http://www.autoitscript.com/trac/autoit/ticket/588http://www.autoitscript.com/forum/index.php?showtopic=82292Thats an interesting way to go about it. It took me a while to understand how it worked. Same principle and based on the php one as well. There I was thinking I was being original I'm guessing this isn't due for inclusion as an AutoIt built in function anytime soon then if it's been a ticket longer than I've on the forums AutoIt Project Listing Link to comment Share on other sites More sharing options...
Xand3r Posted September 7, 2010 Share Posted September 7, 2010 $asdf = 'aaa bbb cc"c ddd eee' $as = StringRegExpReplaceCallback($asdf , "aaa|bbb|ccc" , "upper") MsgBox(0 ,"Callback?", $as) Func StringRegExpReplaceCallback($string , $pattern , $callback) Return StringReplace(Execute('"' & StringRegExpReplace(StringReplace($string , '"' , "\x22") , $pattern , StringFormat('" & %s("\0") & "' , $callback)) & '"') , "\x22" , '"') EndFunc Func upper($text) Return StringUpper($text) EndFunc This works just fine for my scripts Only two things are infinite, the universe and human stupidity, and i'm not sure about the former -Alber EinsteinPractice makes perfect! but nobody's perfect so why practice at all?http://forum.ambrozie.ro Link to comment Share on other sites More sharing options...
wraithdu Posted September 7, 2010 Share Posted September 7, 2010 I like that one. However I'd use a non-printable character instead of "\x22". Something like StringReplace($string , '"' , Chr(26)) Link to comment Share on other sites More sharing options...
wraithdu Posted September 7, 2010 Share Posted September 7, 2010 (edited) Hmm, your original version fails if the string and search pattern have double quotes in them, and you want to search for or manipulate the quote characters. That happens because they are being replaced before making it to the callback function. I've come up with a solution that requires an intermediate function to handle it. Func StringRegExpReplaceCallback($sString , $sPattern , $sCallback) ; replace quotes in pattern and string with Chr(26) (non-printing ASCII character) before running the SRERep ; then change back any remaining Chr(26)'s to quotes before returning the final string Return StringReplace(Execute('"' & StringRegExpReplace(StringReplace($sString, '"', Chr(26)), StringReplace($sPattern, '"', Chr(26)), StringFormat('" & _intSRECallback("${0}", "%s") & "', $sCallback)) & '"'), Chr(26), '"') EndFunc Func _intSRECallback($sString, $sCallback) ; intermediate callback: replace Chr(26) in matches with quotes again so the user callback has unaltered text to work with ; this all happens during the Execute() statement, so we don't need to change remaining quotes back to Chr(26) before returning Return Call($sCallback, StringReplace($sString, Chr(26), '"')) EndFunc Func _callback($s) Return StringUpper($s) EndFunc Func _callback2($s) Return StringReplace($s, '"', "Z") EndFunc ConsoleWrite(StringRegExpReplaceCallback('aa"a bbb cc"c ddd', 'cc"c', "_callback") & @CRLF) ConsoleWrite(StringRegExpReplaceCallback('aa"a bbb cc"c ddd', 'cc"c', "_callback2") & @CRLF) I have no idea how well this works in terms of performance versus some of the other solutions. It may be very one-liner ish, but looks like it could be pretty slow. Edited September 7, 2010 by wraithdu Link to comment Share on other sites More sharing options...
Mat Posted September 7, 2010 Author Share Posted September 7, 2010 Theres a reason I did it properly the first time I think What if I want to use character 26 in my string? You now want a small line to find a character not used in the string... or in the regex pattern... and that includes using matching characters Why not just write your own regex library? AutoIt Project Listing Link to comment Share on other sites More sharing options...
wraithdu Posted September 7, 2010 Share Posted September 7, 2010 Well if you or I want to use Chr(26) in a string for some crazy reason, then we have to go back and rewrite Au3Int as well. Link to comment Share on other sites More sharing options...
Mat Posted September 7, 2010 Author Share Posted September 7, 2010 (edited) Well if you or I want to use Chr(26) in a string for some crazy reason, then we have to go back and rewrite Au3Int as well. I had a funny feeling that would be the reply. I even remember why I chose chr(26)... When I looked at an ascii table they called the character "SUB (substitute)", so I figured that this is exactly what it was for Chr(26) is the "CTRL-Z" code of ASCII/ISO646 keyboards Not sure if that means that Chr(26) actually has a use... I could (in theory) do it with Au3Int, but it would be a big bit of work... I reckon it's a case of writing a new function called _Au3Int_CommaSplit that splits on valid commas (without character changing) rather than replacing invalid ones. That is ultimately what the function does (eventually). That would work. The only problem is I'm getting lost just trying to find where we use the comma strip routine To prove a point I'm going to do it (if I can). Edit: I think we were being a bit stupid not to do this in the first place (Line 77+) _Au3Int_CommaStrip($sLine) $asParams = StringSplit($sLine, ",") ; Undo the comma strips: For $i = 1 To $asParams[0] $asParams[$i] = StringReplace($asParams[$i], Chr(26), ",") Next Edited September 7, 2010 by Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now