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

mri*_*l4c 402 linux string

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

kev*_*kev 534

cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Run Code Online (Sandbox Code Playgroud)

"foo"的出现将被"bar"取代.

  • 如果有人想要寻找更多选项,那么在unix堆栈交换上有一个答案,它涵盖更多用例网站http://unix.stackexchange.com/a/112024/13488 (23认同)
  • @MatthewHerbst来逃避空间,使用\来像`sed -i'/ foo\with\spaces/bar/g'*`.我想你经过这么长时间才发现......但这样一来,其他人就会找到同样的问题. (15认同)
  • 如果字符串中包含空格或特殊字符,这似乎对我不起作用.知道为什么会这样,或者我是否需要逃避它们?谢谢! (12认同)
  • 至少对于我的`sed`版本,`-i`需要一个后面的字符串,它附加到旧的文件名.所以`sed -i .bak的/ foo/bar/g'*.xx`将所有`.xx`文件移动到等效的`.xx.bak`名称,然后使用foo生成`.xx`文件→酒吧替代. (12认同)
  • 对于递归的东西,你可以尝试以下方法.请注意,如果文件列表很大,它将不起作用.`sed -i -e's/foo/bar/g'$(find/home/user/base/dir)` (4认同)
  • 要解决“不是常规文件”问题,只需查找文件: `sed -i 's/foo/bar/g' $(find /path/to/your/folder -type f)` (3认同)
  • @Anaphory 您还可以传入一个空字符串以表示不进行备份(至少在 OS X 上)。例如: `sed -i "" "s/foo/bar/g" *` (2认同)

Cél*_*urd 226

类似于Kaspar的答案,但使用g标志来替换一行中的所有事件.

find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
Run Code Online (Sandbox Code Playgroud)

对于全局不区分大小写:

find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
Run Code Online (Sandbox Code Playgroud)

  • 如果你在OSX上并且你的模式可能包含点并且你想要就地替换(没有备份文件),你应该使用`LC_ALL = C find ./ -type f -exec sed -i''-e's/proc. priv/priv/g'{} \;`(参见[this post](http://stackoverflow.com/questions/19456518/invalid-command-code-despite-escaping-periods-using-sed)和[this] ](http://stackoverflow.com/questions/19242275/re-error-illegal-byte-sequence-on-mac-os-x)) (21认同)
  • 不要从签出的Git仓库的根目录执行此操作.您可能会在.git /`中意外损坏其数据库.一定要把'cd`降到更低的水平. (12认同)
  • 这绝对对我有用,因为它可以使用-name“ * .js”'进行过滤 (2认同)
  • 我刚刚在我的 git repo 中做了这个,现在 `git status` 返回:`error: bad index file sha1 signature....致命:索引文件损坏`。是什么赋予了? (2认同)

pym*_*rco 131

@kev的答案很好,但只影响直接目录中的文件.下面的例子使用grep来递归查找文件.它每次都适合我.

grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用,但是这样做了:`grep --include = {*.php,*.html,*.js} -rnl'./'-e"old-word"| xargs -i @ sed -i's/old-word/new-word/g'@` (13认同)
  • @pymarco你能解释一下这个命令吗?我不知道为什么你必须使用xargs而不是仅仅在`|`之后使用sed,为什么在xargs命令中使用-i`?我在手册中读到它已被弃用,应该使用`-I`代替.是`@`用作模式的开头和结尾的分隔符? (7认同)
  • 在osx上可以:`grep -rli'old-word'* | xargs -I @ sed -i'''s / 2.0.0 / latest / g'@` (3认同)
  • 这个问题是专门针对linux的。 (2认同)

Kas*_*lgi 32

这对我有用:

find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Run Code Online (Sandbox Code Playgroud)

然而,这并没有:sed -i 's/string1/string2/g' *.也许"foo"不是string1而"bar"不是string2.

  • 在OSX上使用:`find ./ -type f -exec sed -i''-e's/string1/string2 /'{} \;` (8认同)

jle*_*evy 31

已经列出了一些标准答案.通常,您可以使用find以递归方式列出文件,然后使用sedperl执行操作.

对于大多数快速使用,您可能会发现命令rpl更容易记住.这是替换(foo - > bar),递归地对所有文件:

rpl -R foo bar .

您可能需要安装它(apt-get install rpl或类似的).

然而,对于涉及正则表达式和反向替换,或文件重命名以及搜索和替换的更艰难的工作,我所知道的最通用和最强大的工具是repren,我写了一段时间的小Python脚本棘手的重命名和重构任务.您可能更喜欢它的原因是:

  • 支持文件重命名以及文件内容的搜索和替换.
  • 在您提交执行搜索和替换之前,请参阅更改.
  • 支持带有后置替换,整个单词,不区分大小写和保留大小写的正则表达式(替换foo - > bar,Foo - > Bar,FOO - > BAR)模式.
  • 适用于多个替换,包括交换(foo - > bar和bar - > foo)或一组非唯一替换(foo - > bar,f - > x).

要使用它,pip install repren.查看自述文件以获取示例.

  • 哇,代表太棒了!只需使用它来更改类名、方法和变量内部单词的一部分,同时重命名文件以匹配 1,000 多个 C++ 头文件和源文件,并且第一次使用一个命令就可以完美运行。谢谢你! (3认同)

Dja*_*omo 27

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

grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'
Run Code Online (Sandbox Code Playgroud)

例如

grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
Run Code Online (Sandbox Code Playgroud)

来源博客


Ign*_*ant 22

鉴于您想搜索字符串search并将其替换为replace跨多个文件,这是我经过实战检验的单行公式

grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
Run Code Online (Sandbox Code Playgroud)

快速grep解释:

  • -R - 递归搜索
  • -i - 不区分大小写
  • -I - 跳过二进制文件(你想要文本,对吧?)
  • -l- 打印一个简单的列表作为输出。其他命令需要

然后将 grep 输出通过管道传输到 sed(通过 xargs),用于实际替换文本。该-i标志将直接更改文件。将其删除为一种“试运行”模式。

  • 如果文本恰好是 url,请记住您在 sed 中使用不同的分隔符,如下所示:'s#search#replace#g' (3认同)

Ily*_*ski 19

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

sed -i 's@old_path@new_path@g'
Run Code Online (Sandbox Code Playgroud)

@符号表示应在后面的字符串中忽略所有特殊字符.

  • 正是我在所有其他答案中都在寻找的东西。即,如何处理特殊字符,例如在更改作为路径的字符串时。谢谢。在其他答案中看起来像是一个很大的疏忽。 (2认同)

小智 17

如果您的字符串中包含正斜杠(/),则可以将分隔符更改为"+".

find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
Run Code Online (Sandbox Code Playgroud)

此命令将在当前目录中递归运行.


小智 11

"foo"的第一行出现将替换为"bar".你可以使用第二行来检查.

grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
Run Code Online (Sandbox Code Playgroud)

  • 你为什么要链接到你的博客?它包含与您的答案完全相同的文本. (6认同)

Paw*_*iel 10

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

replace "old_string" "new_string" -- file_name1 file_name2 file_name3
Run Code Online (Sandbox Code Playgroud)

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

replace "old_string" "new_string" -- *
Run Code Online (Sandbox Code Playgroud)

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

replace "old_string" "new_string" -- *.extension
Run Code Online (Sandbox Code Playgroud)

  • 该实用程序在MySQL包中分发. (4认同)
  • 实际上," - file"应该只是" - ",至少在我的版本中 (2认同)
  • 虽然我想欣赏解决方案,但无需引用常规行即可正常表达. (2认同)
  • 最好添加从哪里获得这个 `replace` 实用程序。没有这些信息,这个答案是不完整的。 (2认同)

Ale*_*elo 6

“您也可以使用find和sed,但是我发现这行perl很好用。

perl -pi -w -e 's/search/replace/g;' *.php
Run Code Online (Sandbox Code Playgroud)
  • -e表示执行以下代码行。
  • -i表示就地编辑
  • -w写警告
  • -p循环

”(摘自http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php

我最好的结果来自使用perl和grep(以确保文件具有搜索表达式)

perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
Run Code Online (Sandbox Code Playgroud)


man*_*cia 5

在找到这个问题(和答案)之前,我确实制定了自己的解决方案。我搜索了“替换”“几个”和“xml”的不同组合,因为那是我的应用程序,但没有找到这个特定的组合。

我的问题:我有 spring xml 文件,其中包含测试用例的数据,其中包含复杂的对象。对java源代码的重构改变了很多类并且不适用于xml数据文件。为了保存测试用例数据,我需要更改分布在多个目录中的所有 xml 文件中的所有类名称。同时保存原始 xml 文件的备份副本(尽管这不是必须的,因为版本控制会将我保存在这里)。

我一直在寻找find+的某种组合sed,因为它在其他情况下对我有用,但不能同时进行多个替换。

然后我发现询问 ubuntu 响应,它帮助我构建了我的命令行:

find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
Run Code Online (Sandbox Code Playgroud)

它工作得很好(嗯,我的箱子有六种不同的替代品)。但请注意,它将触及当前目录下的所有 *.xml 文件。因此,如果您对版本控制系统负责,您可能需要首先进行过滤,然后只传递给sed那些实际拥有您想要的字符串的人;喜欢:

find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
Run Code Online (Sandbox Code Playgroud)


Jus*_*tin 5

真的很蹩脚,但我无法让任何 sed 命令在 OSX 上正常工作,所以我做了这个愚蠢的事情:

:%s/foo/bar/g
:wn
Run Code Online (Sandbox Code Playgroud)

^- 将这三行复制到我的剪贴板中(是的,包括结尾换行符),然后:

六*

并按住 command-v 直到它说没有剩余文件。

愚蠢...黑客...有效...


Mar*_*dor 5

在 MacBook Pro 上,我使用了以下内容(灵感来自/sf/answers/1362004941/):

sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
Run Code Online (Sandbox Code Playgroud)

-i '' 将确保您没有备份。

-e 对于现代正则表达式。

  • `-e` 只是告诉 sed 下一个标记是一个命令。对于扩展的正则表达式,请改用`-E`。 (3认同)