Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
786 views
in Technique[技术] by (71.8m points)

regex - Apply regular expression substitution globally to many files with a script

I want to apply a certain regular expression substitution globally to about 40 Javascript files in and under a directory. I'm a vim user, but doing this by hand can be tedious and error-prone, so I'd like to automate it with a script.

I tried sed, but handling more than one line at a time is awkward, especially if there is no limit to how many lines the pattern might match.

I also tried this script (on a single file, for testing):

ex $1 <<EOF
gs/,(\_s*[]})])/1/
EOF

The pattern will eliminate a trailing comma in any Perl/Ruby-style list, so that "[a, b, c,]" will come out as "[a, b, c]" in order to satisfy Internet Explorer, which alone among browsers, chokes on such lists.

The pattern works beautifully in vim but does nothing if I run it in ex, as per the above script.

Can anyone see what I might be missing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You asked for a script, but you mentioned that you are vim user. I tend to do project-wide find and replace inside of vim, like so:

:args **/*.js | argdo %s/,(\_s*[]})])/1/ge | update

This is very similar to the :bufdo solution mentioned by another commenter, but it will use your args list rather than your buflist (and thus doesn't require a brand new vim session nor for you to be careful about closing buffers you don't want touched).

  • :args **/*.js - sets your arglist to contain all .js files in this directory and subdirectories
  • | - pipe is vim's command separator, letting us have multiple commands on one line
  • :argdo - run the following command(s) on all arguments. it will "swallow" subsequent pipes
    • % - a range representing the whole file
    • :s - substitute command, which you already know about
    • :s_flags, ge - global (substitute as many times per line as possible) and suppress errors (i.e. "No match")
    • | - this pipe is "swallowed" by the :argdo, so the following command also operates once per argument
    • :update - like :write but only when the buffer has been modified

This pattern will obviously work for any vim command which you want to run on multiple files, so it's a handy one to keep in mind. For example, I like to use it to remove trailing whitespace (%s/s+$//), set uniform line-endings (set ff=unix) or file encoding (set filencoding=utf8), and retab my files.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...