z
z copied to clipboard
Crashes when trying to cd to a directory whose name contains "["
I have my albums in directories labeled "[<date>]
awk: cmd. line:37: (FILENAME=- FNR=268) fatal: Invalid range end: //home/<rest of file path>
This is reproducible by simply creating a directory like ooooo[a-
, cding into it, then typing z oooo
. It should crash with a different error:
awk: cmd. line:37: (FILENAME=- FNR=269) fatal: Unmatched [, [^, [:, [., or [=:
Or with just `ooooo['
awk: cmd. line:37: (FILENAME=- FNR=269) fatal: Invalid regular expression:
Probably a simple fix.
Found the issue. It's a simple regex bug on line 173:
gsub(/\[\(\)\[\]\|\]/, "\\\\&", clean_short)
should be
gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short)
.
Basically the regex was escaping the []
for no reason, making it useless. This is such a tiny change it's not even worth a pull request, is it? I'd have to make a fork and all that. It's so simple.
thanks - definitely a gross regex to begin with. When I wrote it there was definitely some edge cases I was sweating but they're lost in the mists of time :( I'm gonna run with this change for a bit before I push it. seems fine so far.
I mean the only difference it makes is that it actually has a decent chance of matching something, since the old regex would only match strings containing [()[]|]
as a substring (and then prefixes the entire thing with a single backslash). The fix just makes your original idea work. Definitely let me know when you push it! :)
My suggested changes at #214 fix this. I'm replacing the gsub
by an index
call.
Ok this is weird. The bug was introduced in https://github.com/rupa/z/commit/eda8015880106a2aef69c77a52f85b32599d4257, and it was the only change in the commit. @rupa can you give some detail on why this commit fixes a supposed problem with mawk
? Or @somasis if he's around
@fictionic, @rupa, this
gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short)
is escaping special characters, so the escaped string can be used with a regular expression matching at
if( matches[x] && x !~ clean_short )
Example:
$ print '() []' | awk '{ if( $1 !~ $2 ) print "Hi" }'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: Unmatched [, [^, [:, [., or [=: /[]/
$ print '() []' | awk '{ gsub(/[\(\)\[\]\|]/, "\\\\&", $2); if( $1 !~ $2 ) print "Hi" }'
Hi
$
This is not a good idea in many ways. First, the change done in eda8015 also broke it for GNU awk (version 4.2.0, API 2.0), so it looks like there's no universal idiom when it comes to regular expressions in awk, at least for bracket expressions like [A-Z]
vs. \[A-Z\]
. Second, the code is trying to do a direct string comparison, so it's much more efficient and easy to use index(s, t)
, which is the function awk provides to do exactly that:
index(s, t) the position in s where the string t occurs, or 0 if it does not.
Example:
$ print '() []' | awk '{ if( index($1, $2) == 0 ) print "Hi" }'
Hi
$
Hence my suggestion at #214. I'm introducing there another change too, which is checking if short
matches only at the beginning of x
, since the code is trying to check if there's a common root among the matches
...
Ok yeah I'm fully on board with your suggestion. @rupa?