带有 -i 选项的 sed 命令在 Mac 上失败,但适用于 Linux

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4247068/
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-03 23:53:24  来源:igfitidea点击:

sed command with -i option failing on Mac, but works on Linux

linuxmacosbashsed

提问by Yarin

I've successfully used the following sedcommand to search/replace text in Linux:

我已成功使用以下sed命令在 Linux 中搜索/替换文本:

sed -i 's/old_link/new_link/g' *

However, when I try it on my Mac OS X, I get:

但是,当我在 Mac OS X 上尝试时,我得到:

"command c expects \ followed by text"

“命令 c 需要 \ 后跟文本”

I thought my Mac runs a normal BASH shell. What's up?

我以为我的 Mac 运行的是普通的 BASH shell。这是怎么回事?

EDIT:

编辑:

According to @High Performance, this is due to Mac sedbeing of a different (BSD) flavor, so my question would therefore be how do I replicate this command in BSD sed?

根据@High Performance,这是由于 Macsed具有不同的 (BSD) 风格,因此我的问题是如何在 BSD 中复制此命令sed

EDIT:

编辑:

Here is an actual example that causes this:

这是导致这种情况的实际示例:

sed -i 's/hello/gbye/g' *

采纳答案by Sinetris

If you use the -ioption you need to provide an extension for your backups.

如果使用该-i选项,则需要为备份提供扩展名。

If you have:

如果你有:

File1.txt
File2.cfg

The command (note the lack of space between -iand ''and the -eto make it work on new versions of Mac and on GNU):

该命令(注意缺乏之间的空间-i,并''-e以使其在Mac和在GNU新版本一起使用):

sed -i'.original' -e 's/old_link/new_link/g' *

Create 2 backup files like:

创建 2 个备份文件,例如:

File1.txt.original
File2.cfg.original

There is no portable way to avoid making backup files because it is impossible to find a mix of sed commands that works on all cases:

没有可移植的方法来避免制作备份文件,因为不可能找到适用于所有情况的 sed 命令组合:

  • sed -i -e ...- does not work on OS X as it creates -ebackups
  • sed -i'' -e ...- does not work on OS X 10.6 but works on 10.9+
  • sed -i '' -e ...- not working on GNU
  • sed -i -e ...- 不适用于 OS X,因为它会创建-e备份
  • sed -i'' -e ...- 不适用于 OS X 10.6 但适用于 10.9+
  • sed -i '' -e ...- 不在 GNU 上工作

NoteGiven that there isn't a sed command working on all platforms, you can try to use another command to achieve the same result.

注意鉴于没有一个 sed 命令适用于所有平台,您可以尝试使用另一个命令来获得相同的结果。

E.g., perl -i -pe's/old_link/new_link/g' *

例如, perl -i -pe's/old_link/new_link/g' *

回答by High Performance Mark

Your Mac does indeed run a BASH shell, but this is more a question of which implementation of sed you are dealing with. On a Mac sed comes from BSD and is subtly different from the sed you might find on a typical Linux box. I suggest you man sed.

您的 Mac 确实运行了 BASH shell,但这更多是您正在处理的 sed 实现的问题。在 Mac 上,sed 来自 BSD,与您可能在典型的 Linux 机器上找到的 sed 略有不同。我建议你man sed

回答by Paused until further notice.

I believe on OS X when you use -i an extension for the backup files is required. Try:

我相信在 OS X 上使用 -i 时需要备份文件的扩展名。尝试:

sed -i .bak 's/hello/gbye/g' *

Using GNU sedthe extension is optional.

使用 GNU 时sed,扩展名是可选的

回答by Ohad Kravchick

Or, you can install the GNU version of sed in your Mac, called gsed, and use it using the standard Linux syntax.

或者,您可以在 Mac 中安装 sed 的 GNU 版本,称为 gsed,并使用标准 Linux 语法使用它。

For that, install gsedusing ports (if you don't have it, get it at http://www.macports.org/) by running sudo port install gsed. Then, you can run sed -i 's/old_link/new_link/g' *

为此,安装gsed使用的端口(如果你没有它,得到它在http://www.macports.org/)运行sudo port install gsed。然后,你可以运行sed -i 's/old_link/new_link/g' *

回答by Lucas

Sinetris' answer is right, but I use this with findcommand to be more specific about what files I want to change. In general this should work (tested on osx /bin/bash):

Sinetris 的回答是正确的,但我将它与find命令一起使用以更具体地说明我想要更改的文件。一般来说,这应该有效(在 osx 上测试/bin/bash):

find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;

In general when using sedwithout findin complex projects is less efficient.

一般来说,在复杂项目中使用sedwithout时find效率较低。

回答by chipiik

This works with both GNU and BSD versions of sed:

这适用于 sed 的 GNU 和 BSD 版本:

sed -i'' -e 's/old_link/new_link/g' *

or with backup:

或有备份:

sed -i'.bak' -e 's/old_link/new_link/g' *

Note missing space after -ioption! (Necessary for GNU sed)

注意-i选项后缺少空格!(对于 GNU sed 是必需的)

回答by ashokrajar

sed -ie 's/old_link/new_link/g' *

Works on both BSD & Linux

适用于 BSD 和 Linux

回答by Sruthi Poddutur

Had the same problem in Mac and solved it with brew:

在 Mac 中遇到了同样的问题并使用以下方法解决了它brew

brew install gnu-sed

and use as

并用作

gsed SED_COMMAND

you can set as well set sedas alias to gsed(if you want):

您可以将sed别名设置为gsed(如果需要):

alias sed=gsed

回答by Dan Kohn

As the other answers indicate, there is not a way to use sed portably across OS X and Linux without making backup files. So, I instead used this Ruby one-liner to do so:

正如其他答案所表明的那样,没有一种方法可以在不制作备份文件的情况下在 OS X 和 Linux 上便携地使用 sed。所以,我改为使用这个 Ruby one-liner 来做到这一点:

ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml

In my case, I needed to call it from a raketask (i.e., inside a Ruby script), so I used this additional level of quoting:

就我而言,我需要从rake任务(即在 Ruby 脚本中)调用它,所以我使用了这个额外的引用级别:

sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}

回答by katopz

Here's how to apply environment variables to template file (no backup need).

以下是如何将环境变量应用于模板文件(无需备份)。

1. Create template with {{FOO}} for later replace.

1. 用 {{FOO}} 创建模板以备后用。

echo "Hello {{FOO}}" > foo.conf.tmpl

2. Replace {{FOO}} with FOO variable and output to new foo.conf file

2. 将 {{FOO}} 替换为 FOO 变量并输出到新的 foo.conf 文件

FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf

Working both macOS 10.12.4and Ubuntu 14.04.5

适用于macOS 10.12.4Ubuntu 14.04.5