Interactive search and replace from shell

前端 未结 8 1866
故里飘歌
故里飘歌 2020-12-29 12:32

Search and replace over multiple files is difficult in my editor. There are plenty of tricks that can be done with find, xargs and sed

相关标签:
8条回答
  • 2020-12-29 12:54

    KISS principle:

    vim
    :args `ls`
    :argdo %s#SEARCH#REPLACE#gec |update
    

    First character afer %s is used as separator

    0 讨论(0)
  • 2020-12-29 12:54

    you can try this tool for find and replace in intercative mode inner a shell

    https://sourceforge.net/projects/isartool/

    No X server is required, and if you want it's recursive in directory using the option -r.

    Ciao

    0 讨论(0)
  • 2020-12-29 12:57

    From jhvaras answer, I've made this bash command to quickly search and replace (to add to .bashrc):

    replace () {
        if [ $# -lt 2 ]
        then
            echo "Recursive, interactive text replacement"
            echo "Usage: replace text replacement"
            return
        fi
    
        vim -u NONE -c ":execute ':argdo %s/$1/$2/gc | update' | :q" $(ag $1 -l)
    }
    

    It's used as follows:

    ~$ replace some_text some_new_text
    

    It uses ag to search in advance, as it's probably faster than letting vim do the work, but you can probably substitute anything else you like. It also calls vim with no plugins for maximum speed, and after it has finished all substitutions it automatically quits and goes back to the shell.

    0 讨论(0)
  • 2020-12-29 13:00

    Here is an enhancement of @jhvaras's answer if you find that you frequently want to do this, or if you only want to search files under version control.

    function SvnProjectSubstitute(replacement)
        execute "args `grep -sl '" . @/ . "' $(svn --recursive list)`; echo -n ''"
        argdo execute "substitute//" . a:replacement . "/gc"
    endfunction
    
    command -nargs=1 -complete=file Gsubstitute call SvnProjectSubstitute(<f-args>)
    

    Notes:

    • As I have formulated it here, it only searches those files which Subversion has under version control from the current directory recursing down. You can off course generalize that or fit it to a different version management system according to your needs.
    • The pattern which is used is the last pattern that was searched for. Once again, if you do not like this, you can fit it to your needs.
    • Gsubstitute is for "global substitute". You can call the command whatever you want but I like this because :Gs seems to fit stylistically into Vim.
    • This is a nice solution if you have a very large number of files, because it takes the onus off of Vim for searching through them all (i.e. it would probably solve this guy's problem too).
    • The do-nothing echo at the end and the -s passed to grep are to cover up an errors that grep encounters. grep gives a non-zero return code even if it does find good results.

    Example use:

    /OldClassName
    :Gs NewClassName
    

    One reason I like using the previous search pattern is it allows you to quickly give a class an entirely different name by placing your cursor on the class, doing a * or a #, and then your :Gs command, which saves you from having to type out the whole search string.

    0 讨论(0)
  • 2020-12-29 13:02

    Just use Vim.

    Start by using find to make a list of all files which need changing like so.

    vim `find . -name '*.c' -exec grep junk {} \;`
    

    That starts vim with all the .c files containing the string junk. Now, in vim make your change to the first file:

    :%s/junk/rubbish/g
    

    And then type :wEnter:nEnter for the next file.

    Now you need to repeat the editing process. If it is only one substitute command and just a few files, then type :UpEnter to repeat the substitute command.

    But if there are a lot, you should use map to create a couple of kestroke macros. The first macro would do the substitute command(s) and the second macro would do the w and n commands to save changes and get the next file.

    I have used this (and older variants with vi) for the past 30 years. In particular, when you encode the two parts of this as two keystroke macros, you can run it very fast because it is easy to hold down the control key, and type a couple of letters, for instance R Y, over and over again. It is faster than the time it takes to write a fully automated script and since this is simple to reproduce, you can do it on any machine that you happen to be working on.

    0 讨论(0)
  • 2020-12-29 13:03

    I would add these modifications to Dillon's answer:

    The -le option should be added to the grep command.

    vim `find . -name '*.c' -exec grep -le '\<junk\>'  {} \;`
    

    Then you are in Vim, but you don't have the opportunity to choose what to replace, add c option at the end for interactive replacements and bufdo at the beginning for walking through every file:

    :bufdo %s/junk/rubbish/gce
    

    Later you save all your work:

    :bufdo wq!
    
    0 讨论(0)
提交回复
热议问题