Jump to content

Extra string funtions


Mat
 Share

Recommended Posts

A few new functions that are very useful, and very simple if you know your RegEx. Most of these i've accumulated over the weeks from questions in h+s, and other projects I've been doing. These are also pretty good examples of how to use RegExp, particularly the \Q and \E tags which I feel are seriously under used. The other thing that should be used more are the {} tags for repetition a fixed amount of times, they've been used in there too.

Func _StringInStrCount ($sString, $sFind, $bCaseSense = False)
   Local $sCase = "(?i)"
   If $bCaseSense = True Then $sCase = ""
   Return UBound (StringRegExp ($sString, $sCase & "(\Q" & $sFind & "\E)", 3))
EndFunc ; ==> _StringInStrCount

Func _StringSplitByLine ($sString, $bCountBlank = False)
   Local $sChar = "+"
   If $bCountBlank = True Then $sChar = "*"
   Return StringRegExp ($sString, "(." & $sChar & ")(?:\n)?", 3)
EndFunc ; ==> _StringSplitByLine

Func _StringAddLine ($sString, $iLine, $sLine, $bCountBlank = False)
   Local $sChar = "+"
   If $bCountBlank = True Then $sChar = "*"
   If Not IsInt ($iLine) Then Return SetError (1, 0, "")
   Return StringRegExpReplace ($sString, "((." & $sChar & "(\n)){" & $iLine & "})(?s)(." & $sChar & ")", "\1" & $sLine & "\3\4")
EndFunc ; ==> _StringAddLine

Func _StringGetLine ($sString, $iLine, $bCountBlank = False)
   Local $sChar = "+"
   If $bCountBlank = True Then $sChar = "*"
   If Not IsInt ($iLine) Then Return SetError (1, 0, "")
   Return StringRegExpReplace ($sString, "((." & $sChar & "\n){" & $iLine & "})(." & $sChar & "\n)((." & $sChar & "\n?)+)", "\2")
EndFunc ; ==> _StringGetLine

Func _StringRemoveLine ($sString, $iLine, $bCountBlank = False)
   Local $sChar = "+"
   If $bCountBlank = True Then $sChar = "*"
   Return StringRegExpReplace ($sString, "((." & $sChar & "\n){" & $iLine - 1 & "})(." & $sChar & "\n?)(." & $sChar & "\n*)", "\1\4")
EndFunc ; ==> _StringRemoveLine

Func _StringGetAfter ($sString, $sChar, $bFirst = True, $bCaseSense = False)
   Local $sGreed = "", $sCase = "(?i)"
   If $bFirst = False Then $sGreed = "(?u)"
   If $bCaseSense = True Then $sCase = ""
   Return StringRegExpReplace ($sString, $sCase & $sGreed & "(?s).*?\Q" & $sChar & "\E(.*)", "\1")
EndFunc ; ==> _StringGetAfter

Func _StringGetBefore ($sString, $sChar, $bFirst = True, $bCaseSense = False)
   Local $sGreed = "", $sCase = "(?i)"
   If $bFirst = False Then $sGreed = "(?u)"
   If $bCaseSense = True Then $sCase = ""
   Return StringRegExpReplace ($sString, $sGreed & "(?s)(.*?)\Q" & $sChar & "\E(.*)\z", "\1")
EndFunc ; ==> _StringGetBefore

Func _StringGetFirstLine ($sString)
   Return StringRegExpReplace ($sString, "\n.*", "")
EndFunc ; ==> _StringGetFirstLine

Func _StringGetLastLine ($sString)
   Return StringRegExpReplace ($sString, ".*\n", "")
EndFunc ; ==> _StringGetLastLine

Mat

Edited by Mat
Link to comment
Share on other sites

Nice functions. You can do a benchmark to see which approach is faster. For example, StringReplace is sometimes a faster and better alternative:

Just a simple benchmark:

Local $a = "ABA" & @CRLF & "CBC" & @CRLF & "DBD"
Local $b

For $i = 1 To 6
    $a &= $a
Next

Local $init = 0

$init = TimerInit()
For $i = 1 To 1000
    $b = UBound (StringRegExp ($a, "(\QB\E)", 3))
Next
ConsoleWrite($b & @TAB & TimerDiff($init) & @CRLF)

$init = TimerInit()
For  $i = 1 To 1000
    StringReplace($a, "B", "", 0, 1)
    $b = @extended
Next
ConsoleWrite($b & @TAB & TimerDiff($init) & @CRLF)

There is no difference in benching for case-(in)sensitivity.

Link to comment
Share on other sites

It could be interesting to see which methods favour longer + shorter strings though... Thats a very interesting set of results there though:

192 1258.41133440144
192 106.548457974407

I tried it on a considerably larger string (FileRead (WinApi.au3)), and StringReplace was considerably faster... From all the tests i've done, StringReplace has been faster actually :) ah well, its all that array handling, if I can find a way around that then I might be able to tighten the gap a bit. I should probably be using StringRegExp and reading that extended value... Yet testing on 6 winapi.au3's:

Local $a = FileRead (StringTrimRight (@AutoitEXE, 11) & "include\WinApi.au3")
Local $b

For $i = 1 To 6
    $a &= $a
Next

Local $init = 0

$init = TimerInit()
    StringRegExpReplace ($a, "(\Q_WinAPI_SetWindowLong\E)", "")
    $b = @Extended
$ret = $b & @TAB & TimerDiff($init) & @CRLF

$init = TimerInit()
    StringReplace($a, "_WinAPI_SetWindowLong", "", 0, 1)
    $b = @extended
$ret &= $b & @TAB & TimerDiff($init)

MsgBox (0, "Results!", $ret)

Mat

Edit: And into 4 digits at last!! I'm not going to post now just to keep on that magic 1000

Edited by Mat
Link to comment
Share on other sites

No problem Zedna:

Func _StringAddLine ($sString, $iLine, $sLine, $bCountBlank = False)
   Local $sChar = "+"
   If $bCountBlank = True Then $sChar = "*"
   If Not IsInt ($iLine) Then Return SetError (1, 0, "")
   Return StringRegExpReplace ($sString, "((." & $sChar & "(\n)){" & $iLine & "})(?s)(." & $sChar & ")", "\1" & $sLine & "\3\4")
EndFunc ; ==> _StringAddLine

Mat

Edit: Now uses current line break character.

Edited by Mat
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...