如何在linux命令行中替换多个文件中的字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11392478/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:44:59  来源:igfitidea点击:

How to replace a string in multiple files in linux command line

linuxstring

提问by mridul4c

I need to replace a string in a lot of files in a folder, with only sshaccess to the server. How can I do this?

我需要替换文件夹中许多文件中的字符串,并且只能ssh访问服务器。我怎样才能做到这一点?

采纳答案by kev

cd /path/to/your/folder
sed -i 's/foo/bar/g' *

Occurrences of "foo" will be replaced with "bar".

“foo”的出现将替换为“bar”。

On BSD systems like macOS, you need to provide a backup extension like -i '.bak'or else "risk corruption or partial content" per the manpage.

在像 macOS 这样的 BSD 系统上,您需要-i '.bak'根据联机帮助页提供备份扩展,否则“风险损坏或部分内容”。

cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *

回答by Kaspar L. Palgi

This worked for me:

这对我有用:

find ./ -type f -exec sed -i 's/string1/string2/' {} \;

Howerver, this did not: sed -i 's/string1/string2/g' *. Maybe "foo" was not meant to be string1 and "bar" not string2.

Howerver,这并不:sed -i 's/string1/string2/g' *。也许“foo”不是string1,而“bar”不是string2。

回答by pymarco

@kev's answer is good, but only affects files in the immediate directory.The example below uses grep to recursively find files. It works for me everytime.

@kev 的回答很好,但只影响直接目录中的文件。下面的例子使用 grep 递归查找文件。它每次都对我有用。

grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @


Command breakdown

命令分解

grep -r: --recursive, recursively read all files under each directory.
grep -l: --print-with-matches, prints the name of each file that has a match, instead of printing matching lines.
grep -i: --ignore-case.

grep -r: --recursive,递归读取每个目录下的所有文件。
grep -l: --print-with-matches,打印每个匹配的文件的名称,而不是打印匹配的行。
grep -i: --ignore-case

xargs: transform the STDIN to arguments, follow this answer.
xargs -i@ ~command contains @~: a placeholder for the argument to be used in a specific position in the ~command~, the @ sign is a placeholder which could replaced by any string.

xargs:将 STDIN 转换为参数,请遵循此答案
xargs -i@ ~command 包含 @~:用于在~command~ 中特定位置使用的参数的占位符,@ 符号是一个可以被任何字符串替换的占位符。

sed -i: edit files in place, withoutbackups.
sed s/regexp/replacement/: substitute string matching regexpwith replacement.
sed s/regexp/replacement/g: global, make the substitution for each match instead of only the first match.

sed -i:就地编辑文件,无需备份。
SED S /的regexp /更换/:替代字符串匹配正则表达式更换
sed s/regexp/replacement/ g: global,对每个匹配进行替换,而不仅仅是第一个匹配。

回答by Céline Aussourd

Similar to Kaspar's answer but with the g flag to replace all the occurrences on a line.

类似于 Kaspar 的答案,但使用 g 标志替换一行中的所有出现。

find ./ -type f -exec sed -i 's/string1/string2/g' {} \;

For global case insensitive:

对于全局不区分大小写:

find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;

回答by Dennis

grep --include={*.php,*.html} -rnl './' -e "old" | xargs -i@ sed -i 's/old/new/g' @

回答by Pawel Dubiel

If you have list of files you can use

如果您有可以使用的文件列表

replace "old_string" "new_string" -- file_name1 file_name2 file_name3

If you have all files you can use

如果您拥有可以使用的所有文件

replace "old_string" "new_string" -- *

If you have list of files with extension, you can use

如果您有带扩展名的文件列表,则可以使用

replace "old_string" "new_string" -- *.extension

回答by Djacomo

To replace a string in multiple files you can use:

要替换多个文件中的字符串,您可以使用:

grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'

E.g.

例如

grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'

Source blog

源博客

回答by Anaphory

The stream editor does modify multiple files “inplace” when invoked with the -iswitch, which takes a backup file ending as argument. So

当使用-i开关调用时,流编辑器确实会“就地”修改多个文件,该开关以备份文件结尾作为参数。所以

sed -i.bak 's/foo/bar/g' *

replaces foowith barin all files in this folder, but does not descend into subfolders. This will however generate a new .bakfile for every file in your directory. To do this recursively for all files in this directory and all its subdirectories, you need a helper, like find, to traverse the directory tree.

内容替换foobar在此文件夹中的所有文件,但不会下降到子文件夹。但是,这将为.bak目录中的每个文件生成一个新文件。要对该目录及其所有子目录中的所有文件递归执行此操作,您需要一个助手(如find)来遍历目录树。

find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *

findallows you further restrictions on what files to modify, by specifying further arguments like find ./ -name '*.php' -or -name '*.html' -print0, if necessary.

find允许您进一步限制要修改的文件find ./ -name '*.php' -or -name '*.html' -print0,如有必要,可通过指定更多参数(如)。



Note: GNU seddoes not require a file ending, sed -i 's/foo/bar/g' *will work, as well; FreeBSD seddemands an extension, but allows a space in between, so sed -i .bak s/foo/bar/g *works.

注意:GNUsed不需要文件结尾,sed -i 's/foo/bar/g' *也可以工作;FreeBSDsed需要一个扩展,但允许中间有一个空间,所以sed -i .bak s/foo/bar/g *可以。

回答by BBW Before Windows

script for multiedit command

多编辑命令脚本

multiedit [-n PATTERN] OLDSTRING NEWSTRING

From Kaspar's answer I made a bash script to accept command line arguments and optionally limit the filenames matching a pattern. Save in your $PATH and make executable, then just use the command above.

从 Kaspar 的回答中,我制作了一个 bash 脚本来接受命令行参数并可选择限制与模式匹配的文件名。保存在您的 $PATH 中并使可执行文件,然后只需使用上面的命令。

Here's the script:

这是脚本:

#!/bin/bash
_help="\n
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n

[-n PATTERN] option limits to filenames matching PATTERN\n
Note: backslash escape special characters\n
Note: enclose STRINGS with spaces in double quotes\n
Example to limit the edit to python files:\n
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n"

# ensure correct number of arguments, otherwise display help...
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi
if [  == "-n" ]; then  # if -n option is given:
        # replace OLDSTRING with NEWSTRING recursively in files matching PATTERN
        find ./ -type f -name "" -exec sed -i "s///g" {} \;
else
        # replace OLDSTRING with NEWSTRING recursively in all files
        find ./ -type f -exec sed -i "s///" {} \;
fi

回答by Ilya Suzdalnitski

To replace a path within files (avoiding escape characters) you may use the following command:

要替换文件中的路径(避免转义字符),您可以使用以下命令:

sed -i 's@old_path@new_path@g'

The @ sign means that all of the special characters should be ignored in a following string.

@ 符号意味着在后面的字符串中应该忽略所有特殊字符。