Reputation: 87
I'm trying to formulate a regular expression that matches the names of a set of files I would like to batch process in Vim but am finding that I cannot seem to use \| (regex OR) as expected...
Specifically, I would like to create an argument list consisting of the following files in the current directory:
f0148.e, f0149.e, f0150.e ... f0159.e (i.e., 12 files total)
The vim command I entered goes as follows:
:arg f01\(\(4[89]\)\|\(5[0-9]\)\).e
Vim completes this command without any noticeable result -- there's no message and the output from :args remains unchanged (doesn't produce the desired list of file names).
If I split up the regular expression to:
:arg f01\(\(4[89]\)\).e
(note: leaving parenthesis here as in above full expression)
...and...
:arg f01\(\(5[0-9]\)\).e
... then :args
produces f0148.e f0149.e
and f0150.e ... f0159.e
respectively (as desired).
Also, if I enter the above mentioned list of file names in a text file and use the above mentioned regular expression as a search pattern (i.e., /f01\(\(4[89]\)\|\(5[0-9]\)\).e
), it works just as desired.
Thus, I determined that the alternation (\|)
is somehow causing the the expression to fail. Please note that I'm using Vim on Windows 7, if this is relevant (since both backslash and pipe are valid symbols at the Windows command prompt).
A quick workaround would be to use:
:arg f014[89].e
:argadd f015[0-9].e
...but I would really like to figure out how to make the above regular expression work.
Thanks for your help!
Upvotes: 1
Views: 1414
Reputation: 79185
I could suggest:
:let file_list = filter(split(globpath('.','**'),nr2char(10)), 'v:val =~ ''f01\(\(4[89]\)\|\(5[0-9]\)\)\.e'' ')
:execute 'args ' . join(map(file_list,'fnameescape(v:val)'),' ')
How this works:
globpath('.','**')
makes a list of all files in current directory and all subdirectories. :help globpath()
.split(..., nr2char(10))
will make a list of it, because the separator was Line Feedfilter(..., 'v:val =~ ''pattern'' ')
filters the list keeping only items matching pattern. :help v:val
. Doubling single quote is escaping them inside single quote string.map(..., fnameescape())
escapes all spaces and backslashesjoin()
adds spaces between file namesIf you want to make it a function you can put this into your vimrc:
function! ArgsPattern(pat)
let file_list = filter(split(globpath('.','**'),nr2char(10)), 'v:val =~ ''' . substitute(a:pat,"'","''",'g') . '''')
execute 'args ' . join(map(file_list,'fnameescape(v:val)'),' ')
endfunction
command! -nargs=+ ArgsPattern call ArgsPattern(<q-args>)
And then you only have to do:
:ArgsPattern f01\(\(4[89]\)\|\(5[0-9]\)\)\.e
Note that if there is no match, then the execute
command inside the function evaluates to :args
and therefore the list of your current arguments are printed.
Upvotes: 2