Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

InStr() enchancements


  • Please log in to reply
14 replies to this topic
infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
1. Support negative StartingPos for starting a certain number of characters from the end and going right to left.
2. Add an Occurrence param to find the n occurrence of Needle in the direction specified by StartingPos.

So the docs might read something like this: (green=new, red=omitted for brevity)

InStr(Haystack, Needle [, CaseSensitive = false, StartingPos = 1, Occurrence = 1]): Returns the position of the first occurrence of the string Needle in the string Haystack. ... If StartingPos is omitted, it defaults to 1 (the beginning of Haystack). Otherwise, specify 2 to start at Haystack's second character, 3 to start at the third, etc. If StartingPos is beyond the length of Haystack, 0 is returned. If StartingPos is less than or equal to 0, the search is conducted in reverse (right-to-left) so that the rightmost match is found starting at StartingPos characters from the right. Specify Occurrence greater than 1 to find the Nth occurrence of Needle in the direction specified by StartingPos ....


If this is added it would give a sorely needed expression replacement for StringGetPos, without breaking any current syntax.

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
In the meantime see <!-- m -->http://www.autohotke... ... 523#334523<!-- m -->

Edit: this
MsgBox % _InStr("this is a test this is a test", "this", False, 0)
doesn't seem to produce the correct result :?: it returns 0 and if I understand it correctly it should be 16

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
No loops or DllCall needed:
MsgBox % InStr("this is a test this is a test", "this", False, 0)

InStr(Haystack, Needle, CaseSensitive=False, StartingPos=1, Count=1) {
    scs := A_StringCaseSense
    StringCaseSense % CaseSensitive ? "On" : A_StringCaseSense="Off" ? "Off" : "Locale"
    StringGetPos, p, Haystack, % Needle, % (StartingPos>0 ? "L" : "R") . Count, % Abs(StartingPos) - (StartingPos>0)
    StringCaseSense % scs
    return ErrorLevel ? 0 : p+1
}
I agree that it should be built in.

I was not sure whether to return a negative or positive offset when a negative StartingPos was sent, but I went with negative.

According to the current documentation, trik went the wrong way. :)

Regardless of the value of StartingPos, the returned position is always relative to the first character of Haystack.
Source: Functions - InStr



SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Very useful, thanks I will use it for sure.

infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
... but this completely misses the point. We need this functionality built in to ahk directly. If I wanted a wrapper function I would have made it myself and shut up. I made this thread because we need a built-in, expression alternative to StringGetPos and imo adding this functionality directly to InStr() is the simplest, easiest, and most direct method of achieving this goal without breaking any current scripts or negatively impacting performance.

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
I agree with infogulch.

No signature.


SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

I agree that it should be built in.


+1

MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009
I agree. Also, this addition would not break any currently existing scripts.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio Fran├ža -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


dR*
  • Guests
  • Last active:
  • Joined: --
agree++

greets
derRaphael

BigVent
  • Moderators
  • 217 posts
  • Last active: Nov 10 2015 09:14 PM
  • Joined: 29 May 2008
I concur as well! +1
~BigVent

ChalamiuS
  • Moderators
  • 176 posts
  • Last active:
  • Joined: 04 Jun 2006

I agree that it should be built in.

This.

tidbit
  • Administrators
  • 2709 posts
  • Hates playing Janitor
  • Last active: Jan 15 2016 11:37 PM
  • Joined: 09 Mar 2008
i can't believe i'm wasting my 666'th post on this (actually my 667's but some mod deleted my other one...)

I was peer-pressured to agree with infogulch. sooo
+1

rawr. be very afraid
*poke*
. Populate the AutoHotkey city. Pointless but somewhat fun. .


ruespe
  • Members
  • 567 posts
  • Last active: Dec 01 2014 07:59 PM
  • Joined: 17 Jun 2008
Totaly agree. Just one addition:

InStr(Haystack, Needle [, CaseSensitive = false, StartingPos = 1, Occurrence = 1,ExactOccurrence=false]): Returns the position of the first occurrence of the string Needle in the string Haystack. ... If StartingPos is omitted, it defaults to 1 (the beginning of Haystack). Otherwise, specify 2 to start at Haystack's second character, 3 to start at the third, etc. If StartingPos is beyond the length of Haystack, 0 is returned. If StartingPos is less than or equal to 0, the search is conducted in reverse (right-to-left) so that the rightmost match is found starting at StartingPos characters from the right. Specify Occurrence greater than 1 to find the Nth occurrence of Needle in the direction specified by StartingPos. If Occurrence is greater then the last found occurrence, the position of the last found occurrence will be returned (if there is one), unless ExactOccurence is set to True ....



Zaelia
  • Members
  • 754 posts
  • Last active: Jan 17 2015 02:38 AM
  • Joined: 31 Oct 2008
+1

But with "R" option it's the mess... I think we need something like this % StrLen(%Haystack%)-Abs(StartingPos)
In other word, StartingPos is the offset position always in left to right read

If we change InStr() in AHK I really hope that Starting search position will be always in left to right, do you know example when right to left position is need ?

Howerver is not a problem, something like this:
StrPos(Haystack, Needle, PosFlag="1", Count="1") {
  StringGetPos, pos, Haystack, % Needle, % (PosFlag>0 ? "L": "R") . Count, % PosFlag>0 ? PosFlag : StrLen(%Haystack%)-PosFlag
  return pos
}


Zaelia
  • Members
  • 754 posts
  • Last active: Jan 17 2015 02:38 AM
  • Joined: 31 Oct 2008
Function is very slow compared to ahk command, so I write this script for full support right to left order, I hope you like it, need other test for fix bug and optimize it...

note: It's crazy with StringGetPos with "right to left" to have returned position in "left to right" and StartPosition in "right to left"... problem appear in string like this "0000000needle00000000000needle000needle" for search the needle at middle...

About compatibility, InStr is crap for right to left so maybe we need a command like StrPos(), but it's my point of view...


;   myPos := StrPos(Haystack, Needle, p=1, w="L", m=1, s=0, r=0)
; Haystack
;   Whose contents will be searched
; Needle
;   The string to search for
; Position or Pointer (p and return of this function):
;   If positive, it is a position in left to right
;   If negative, it is a position in right to left
;   If 0, it is an error
;   If ommited, the default is 1
; Direction or Way (w) :
;   If not specified, the search direction is in normal way (left to right)
;   Else use "R" for reverse it (right to left)
; Occurence or Match (m) :
;   If ommited, the default is 1
;   Else the function find the umpteenth occurence
; String Case Sensitivity (s) :
;   If not specified, the function use the current case sensitivity
;   Else use "On", "Off" or "Locale"
; Relative or Returned Result (r) :
;   If not specified, the return have the same reading order and sign than pos
;   Else use "R" for force the return position in right to left
;   And "L" for force the return position in left to right
; note: R = right to left, reverse, relative,...


StrPos(Haystack, Needle, p=1, w="L", m=1, s=0, r=0) {
    s0 := A_StringCaseSense
StringCaseSense % s="On" ? "On" : s="Off" ? "Off" : s="Locale" ? "Locale" : s0
StringGetPos, result, Haystack, % Needle, % w . m, % ((w="L" && p>0) || (w="R" && p<0)) ? abs(p)-1 : StrLen(Haystack)-abs(p)
StringCaseSense % s0
    return  ErrorLevel ? 0 : ((p<0 && r=0) || (r="R")) ? -(StrLen(Haystack)-result+1-StrLen(Needle)) : result+1
}