How to grep and replace

后端 未结 9 1545
囚心锁ツ
囚心锁ツ 2020-11-27 08:47

I need to recursively search for a specified string within all files and subdirectories within a directory and replace this string with another string.

I know that t

相关标签:
9条回答
  • 2020-11-27 09:20

    This works best for me on OS X:

    grep -r -l 'searchtext' . | sort | uniq | xargs perl -e "s/matchtext/replacetext/" -pi
    

    Source: http://www.praj.com.au/post/23691181208/grep-replace-text-string-in-files

    0 讨论(0)
  • 2020-11-27 09:20

    Other solutions mix regex syntaxes. To use perl/PCRE patterns for both search and replace, and only process matching files, this works quite well:

    grep -rlIZPi 'match1' | xargs -0r perl -pi -e 's/match2/replace/gi;'
    

    match1 and match2 are usually identical but match1 can be simplified to remove more advanced features that are only relevant to the substitution, e.g. capturing groups.

    Translation: grep recursively and list matching filenames, each separated by nul to protect any special characters; pipe any filenames to xargs which is expecting a nul-separated list; if any filenames are received, pass them to perl to perform the actual substitutions.

    For case-sensitive matching, drop the i flag from grep and the i pattern modifier from the s/// expression, but not the i flag from perl itself. Remove the I flag from grep to include binary files.

    0 讨论(0)
  • 2020-11-27 09:24

    Be very careful when using find and sed in a git repo! If you don't exclude the binary files you can end up with this error:

    error: bad index file sha1 signature 
    fatal: index file corrupt
    

    To solve this error you need to revert the sed by replacing your new_string with your old_string. This will revert your replaced strings, so you will be back to the beginning of the problem.

    The correct way to search for a string and replace it is to skip find and use grep instead in order to ignore the binary files:

    sed -ri -e "s/old_string/new_string/g" $(grep -Elr --binary-files=without-match "old_string" "/files_dir")
    

    Credits for @hobs

    0 讨论(0)
  • 2020-11-27 09:25

    Another option is to use find and then pass it through sed.

    find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \;
    
    0 讨论(0)
  • 2020-11-27 09:31

    Usually not with grep, but rather with sed -i 's/string_to_find/another_string/g' or perl -i.bak -pe 's/string_to_find/another_string/g'.

    0 讨论(0)
  • 2020-11-27 09:36

    Here is what I would do:

    find /path/to/dir -type f -iname "*filename*" -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
    

    this will look for all files containing filename in the file's name under the /path/to/dir, than for every file found, search for the line with searchstring and replace old with new.

    Though if you want to omit looking for a specific file with a filename string in the file's name, than simply do:

    find /path/to/dir -type f -print0 | xargs -0 sed -i '/searchstring/s/old/new/g'
    

    This will do the same thing above, but to all files found under /path/to/dir.

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