 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sat Apr 25, 2009 8:47 pm Post subject: inStr question |
|
|
I'm trying to use inStr to find the last occurance of a backslash ("\"). However, I want to omit the last character. The goal is to navigate one folder upward (toward the root).
| Code: | Folder := "C:\FolderA\FolderB\"
;works using StringGetPos
StringGetPos, index, Folder, % "\", R, 1
index++
if (index)
{
Folder := subStr(Folder, 1, index)
;outputs "C:\FolderA\"
MsgBox, % Folder
}
|
| Code: | Folder := "C:\FolderA\FolderB\"
;doesn't work using inStr (index = 0)
index := inStr(Folder, "\", false, -1)
if (index)
{
Folder := subStr(Folder, 1, index)
MsgBox, % Folder
}
|
_________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Sat Apr 25, 2009 9:10 pm Post subject: |
|
|
The value for index is going to be the count including the character you're trying to omit, no?
| Code: | Folder := "C:\FolderA\FolderB\"
index := inStr(Folder,"\",false,0)
if (index)
{
Folder := subStr(Folder,1,(index - 1))
MsgBox, % Folder
} |
_________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sat Apr 25, 2009 9:39 pm Post subject: |
|
|
| sinkfaze wrote: | | The value for index is going to be the count including the character you're trying to omit, no? |
I'm not sure I understand the question, so I'm not really sure how to respond, sorry.
The goal is to transverse up one directory. I want it to work regardless if the directory has a trailing "\" or not. Your example doesn't output what I need because it only removes the trailing "\". I want it to remove the entire directory - resulting in "C:\FolderA\". _________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 7187
|
Posted: Sat Apr 25, 2009 10:04 pm Post subject: |
|
|
| animeaime wrote: | | The goal is to transverse up one directory. |
I would do it like
| Code: | Folder := "C:\FolderA\FolderB\"
DllCall( "shlwapi\PathRemoveBackslashA", Str,Folder )
SplitPath,Folder,,Folder
MsgBox, % Folder "\" |
_________________ Suresh Kumar A N |
|
| Back to top |
|
 |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sat Apr 25, 2009 10:11 pm Post subject: |
|
|
ic. Very nice. One question - what's the difference between using a DllCall and simply removing the backslash?
| Code: | Folder := "C:\FolderA\FolderB"
if subStr(Folder, 0) = "\"
StringTrimRight, Folder, Folder, 1
SplitPath,Folder,,Folder
MsgBox, % Folder "\"
|
_________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Sat Apr 25, 2009 10:57 pm Post subject: |
|
|
| animeaime wrote: | | I'm not sure I understand the question, so I'm not really sure how to respond, sorry. |
That's okay, I didn't read your question correctly.
SKAN pretty much covered my answer. AFAIK InStr doesn't have the "looking" ability of StringGetPos, so you'd have to do something like this if you know it's always going to be the 2nd occurrence from the right:
| Code: | Folder := "C:\FolderA\FolderB\"
index := InStr(SubStr(Folder,1,InStr(Folder, "\", false, 0) - 1),"\", false, 0)
if (index)
{
Folder := subStr(Folder, 1, index)
MsgBox, % Folder
} |
Not too confusing, huh?
EDIT: You could also use RegExMatch:
| Code: | Folder := "C:\FolderA\FolderB\"
RegExMatch(Folder,"^(?P<Folder>C:\\.*?\\)",Root)
if (RootFolder)
MsgBox, % RootFolder |
_________________ Try Quick Search for Autohotkey or see the tutorial for newbies.
Last edited by sinkfaze on Sat Apr 25, 2009 11:08 pm; edited 1 time in total |
|
| Back to top |
|
 |
rulfzid
Joined: 27 Nov 2008 Posts: 62
|
Posted: Sat Apr 25, 2009 11:04 pm Post subject: |
|
|
Using regular expressions:
| Code: | folder := "C:\folderA\folderB\"
MsgBox % GetOneDirUp( folder )
GetOneDirUp( folder ) {
RegExMatch( folder, "(.*)(?=\\.+?)(?:\\(?!=.))?", up_a_dir )
if not up_a_dir ; we're already at a drive
return 0
return up_a_dir1
}
|
|
|
| Back to top |
|
 |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sat Apr 25, 2009 11:35 pm Post subject: |
|
|
Thanks for all the feedback. I think I'm going to stick with my current design. The others seem more complicated than they are worth. I like SKAN's solution, but no matter how many times I look at it, it's not very intuitive for me. I don't think to use SplitPath like that, so it will only cause confusion reading the code.
As far as the RegExes go, I think they are overkill. It's been mentioned that RegEx should be avoided, when possible, due to performance. Granted, performance isn't really an issue here, but I think RegEx only complicates things.
Sorry for the fuss. It seems that the answer to my question is that inStr can't be used how I want, which is a shame. I think it would be really nice to have inStr be a wrapper for the StringGetPos command, but at least we have the StringGetPos command to use. Thanks again for all the ideas. _________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Sun Apr 26, 2009 12:04 am Post subject: |
|
|
| animeaime wrote: | | As far as the RegExes go, I think they are overkill. It's been mentioned that RegEx should be avoided, when possible, due to performance. |
To each their own, but in this case it would take quite a tremendous amount of repetitions to bear out a significant difference in performance, IMO:
| Code: | Folder := "C:\FolderA\FolderB\"
QPC()
StringGetPos, index, Folder, % "\", R, 1
index++
if (index)
Folder := subStr(Folder, 1, index)
T1 := QPC()
QPC()
RegExMatch(Folder,"^(?P<Folder>C:\\.*?\\)",Root)
if (RootFolder)
Folder := RootFolder
T2 := QPC()
MsgBox % "StringGetPos: " T1 "`nRegExMatch: " T2 ""
QPC() {
Static Freq, LastCount
If !Freq
DllCall("QueryPerformanceFrequency", "Int64*", Freq)
DllCall("QueryPerformanceCounter", "Int64*", Count)
Return (Count-LastCount)/Freq, LastCount:=Count
} |
My results averaged over 50 runs:
| results wrote: | StringGetPos: 0.000019
RegExMatch: 0.000032 |
_________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sun Apr 26, 2009 12:14 am Post subject: |
|
|
@sinkfaze
Well, for your RegEx, it doesn't work when there are more than two subfolders.
| Code: | Folder := "C:\FolderA\FolderB\FolderC\"
RegExMatch(Folder,"^(?P<Folder>C:\\.*?\\)",Root)
;outputs "C:\FolderA\"
if (RootFolder)
MsgBox, % RootFolder
|
The other RegEx looks too complicated for the problem at hand - in light of the two non-RegEx solutions already posted - like you said, personal preferance. I like code that I can read - this is one of my, personal, requirements. If I can't read it and make sense of it quickly, then I rewrite the code in a more readable form. Of course, I make no quarantee that someone else can read my code . _________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
rulfzid
Joined: 27 Nov 2008 Posts: 62
|
Posted: Sun Apr 26, 2009 12:17 am Post subject: |
|
|
In fact, comparing stringgetpos, splitpath, and regexmatch:
| Code: | folder := "C:\foldera\folderb\"
num = 10000
TickCount()
Loop % num
f := GetOneDirUp_splitpath( folder )
splitpath_time := TickCount()/1000
Loop % num
f := GetOneDirUp_regex( folder )
regex_time := TickCount()/1000
Loop % num
f := GetOneDirUp_stringgetpos( folder )
stringgetpos_time := TickCount()
Msgbox % "SplitPath: " splitpath_time " seconds`nRegex: " regex_time " seconds`nStringGetPos: " stringgetpos_time " seconds"
clipboard := "SplitPath: " splitpath_time " seconds`nRegex: " regex_time " seconds`nStringGetPos: " stringgetpos_time " seconds"
GetOneDirUp_regex( folder ) {
RegExMatch( folder, "(.*)(?=\\.+?)(?:\\(?!=.))?", up_a_dir )
if not up_a_dir ; we're already at a drive
return 0
return up_a_dir1
}
GetOneDirUp_splitpath( folder ) {
if subStr(Folder, 0) = "\"
StringTrimRight, Folder, Folder, 1
SplitPath,Folder,,Folder
return folder
}
GetOneDirUp_stringgetpos( folder ) {
StringGetPos, index, Folder, % "\", R, 1
index++
if index
return subStr(Folder, 1, index)
}
TickCount() {
Static LastCount
Return (A_TickCount-LastCount)/1000, LastCount := A_TickCount
} |
Setting num to 10000 gives me:
| Quote: | SplitPath: 0.000031 seconds
Regex: 0.000250 seconds
StringGetPos: 0.063000 seconds |
Setting num to 100000 gives me:
| Quote: | SplitPath: 0.000625 seconds
Regex: 0.002875 seconds
StringGetPos: 0.625000 seconds |
Splitpath is consisently the fastest, but unless you're running millions of these, you're not seeing any performance differences between splitpath and regex. StringGetPos, weirdly, is slower by a factor of several hundred. I guess mainly I'm pointing out that regular expressions are actually pretty darn fast.
@Sinkfaze
I wonder what causes the differences in performance between your regex and mine. I'd guess it's using the named subpatterns? |
|
| Back to top |
|
 |
sinkfaze
Joined: 19 Mar 2008 Posts: 2721 Location: the tunnel(?=light)
|
Posted: Sun Apr 26, 2009 12:27 am Post subject: |
|
|
| animeaime wrote: | | Well, for your RegEx, it doesn't work when there are more than two subfolders. |
Very true, I was making a solution limited to only two instances. RegExReplace would make it more adapatable to more situations:
| Code: | Folder := "C:\FolderA\FolderB\FolderC\"
MsgBox, % RegExReplace(Folder,"(?P<Folder>C:\\[\w\s-]+).*","${Folder}\") |
_________________ Try Quick Search for Autohotkey or see the tutorial for newbies. |
|
| Back to top |
|
 |
animeaime
Joined: 04 Nov 2008 Posts: 1046
|
Posted: Sun Apr 26, 2009 12:27 am Post subject: |
|
|
@rulfzid: You forgot to divide by 1000 for the StringGetPos
| Code: | folder := "C:\foldera\folderb\"
num = 10000
TickCount()
Loop % num
f := GetOneDirUp_splitpath( folder )
splitpath_time := TickCount()/1000
Loop % num
f := GetOneDirUp_regex( folder )
regex_time := TickCount()/1000
Loop % num
f := GetOneDirUp_stringgetpos( folder )
stringgetpos_time := TickCount()/1000
Msgbox % "SplitPath: " splitpath_time " seconds`nRegex: " regex_time " seconds`nStringGetPos: " stringgetpos_time " seconds"
clipboard := "SplitPath: " splitpath_time " seconds`nRegex: " regex_time " seconds`nStringGetPos: " stringgetpos_time " seconds"
GetOneDirUp_regex( folder ) {
RegExMatch( folder, "(.*)(?=\\.+?)(?:\\(?!=.))?", up_a_dir )
if not up_a_dir ; we're already at a drive
return 0
return up_a_dir1
}
GetOneDirUp_splitpath( folder ) {
if subStr(Folder, 0) = "\"
StringTrimRight, Folder, Folder, 1
SplitPath,Folder,,Folder
return folder
}
GetOneDirUp_stringgetpos( folder ) {
StringGetPos, index, Folder, % "\", R, 1
index++
if index
return subStr(Folder, 1, index)
}
TickCount() {
Static LastCount
Return (A_TickCount-LastCount)/1000, LastCount := A_TickCount
} |
_________________ As always, if you have any further questions, don't hesitate to ask.
Add OOP to your scripts via the Class Library. Check out my scripts. |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2224
|
Posted: Sun Apr 26, 2009 12:33 am Post subject: |
|
|
In this case, RegEx is not that un-intuitive, really verbatim to what we actually carried out.
| Code: | Folder := "C:\FolderA\FolderB\FolderC\"
;Folder := "C:\FolderA\FolderB\FolderC"
RegExMatch(Folder,"^.*\\(?=[^\\]+\\?$)",Root)
MsgBox % Root
|
|
|
| Back to top |
|
 |
rulfzid
Joined: 27 Nov 2008 Posts: 62
|
Posted: Sun Apr 26, 2009 12:33 am Post subject: |
|
|
Doh!
You are correct.
But my assertion that you'd need to be running these millions of times for any significant difference still stands.
Apologies for incorrectly jumping guns. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|