Apply regular expression substitution globally to many files with a script

前端 未结 5 1659
小蘑菇
小蘑菇 2020-12-17 00:58

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 ted

相关标签:
5条回答
  • 2020-12-17 01:05

    you can use a combination of the find command and sed

    find /path -type f -iname "*.js" -exec sed -i.bak 's/,[ \t]*]/]/' "{}" +;
    
    0 讨论(0)
  • 2020-12-17 01:08

    If you are on windows, Notepad++ allows you to run simple regexes on all opened files.

    Search for ,\s*\] and replace with ]

    should work for the type of lists you describe.

    0 讨论(0)
  • 2020-12-17 01:20

    1) Open all the files with vim:

    bash$ vim $(find . -name '*.js')
    

    2) Apply substitute command to all files:

    :bufdo %s/,\(\_\s*[\]})]\)/\1/ge
    

    3) Save all the files and quit:

    :wall
    :q
    

    I think you'll need to recheck your search pattern, it doesn't look right. I think where you have \_\s* you should have \_s* instead.

    Edit: You should also use the /ge options for the :s... command (I've added these above).

    0 讨论(0)
  • 2020-12-17 01:25

    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.

    0 讨论(0)
  • 2020-12-17 01:27

    You can automate the actions of both vi and ex by passing the argument +'command' from the command line, which enables them to be used as text filters.

    In your situation, the following command should work fine:

    find /path/to/dir -name '*.js' | xargs ex +'%s/,\(\_\s*[\]})]\)/\1/g' +'wq!'

    0 讨论(0)
提交回复
热议问题