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

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


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


“命令c期望\后面跟着文字”


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

编辑:

根据@High Performance,这是由于Mac sed具有不同的(BSD)风格,所以我的问题将是如何做的。我在BSD sed中复制了此命令?

编辑:

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

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


评论

这意味着sed作为命令在您的数据中看到“ c”。您正在使用变量吗?请张贴一些更能代表实际命令和您正在处理的数据的内容。您可以通过执行echo x |来简单演示该错误。 sed c。

@Dennis,上面的简单命令会导致这种情况,尽管它处理的数据是整个网站(我正在转换所有图像链接),包括html和css文件...

#1 楼

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

如果您具有:

File1.txt
File2.cfg


命令(请注意-i''之间以及-e之间缺少空间,无法在新版本的Mac和GNU上使用):

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


创建2个备份文件,如:

File1.txt.original
File2.cfg.original


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



sed -i -e ...-在创建-e备份时不能在OS X上运行

sed -i'' -e ...-在OS X 10.6上不能运行,但在10.9+上可以运行

sed -i '' -e ...-在GNU上不起作用

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

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

评论


我遇到过同样的问题。感谢您的解决方案。但是,在我尝试使用“ man sed”查找“ -i”的描述的地方,没有任何关于使用-i''忽略备份的内容。这是我的第一责备。其次,当出现错误“命令期望\后跟文本”时,为什么不直接告诉我们它期望选项'-i'的备份名称!这样的事情无处不在:您得到一个错误,而不是为什么出错,然后搜索手册,该手册对此一无所知。然后您用谷歌搜索其他人也有同样的问题。我的意思是,为什么不在手册中举例说明?

–lukmac
2012年8月19日在22:43

或告诉我们为什么会出现错误,而不是仅显示一条信息,指出发生错误。这是对所有工具制造商的建议,前提是他们可以阅读此评论。

–lukmac
2012年8月19日在22:45

@lukmac据sed所知,您DID提供了一个备份后缀。备份后缀为s / old_link / new_link / g。此后的下一个参数应该是编辑命令。因为它将命令解释为备份名称,所以它将第一个文件名作为编辑命令,但是它们无效。

– Barmar
2014年3月20日在0:52

这将永远是一个问题吗? Apple是否可以通过某种方式创建OSX所解决的GNU解决方案/程序包?或者,GNU sed无法支持sed -i''-e ...吗?

–blong
16-11-21在17:06



sed -i''-e在Mac 10.14上似乎无法正常工作

– MoOx
18/12/6在16:13

#2 楼

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

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


使用GNU sed扩展名是可选的。

#3 楼

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

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


,或者与备份:

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


注意-i选项后缺少空间! (GNU sed必需)

评论


第一个在OSX上不起作用(我已经在10.6.8上对其进行了测试)

– marcin
13年11月11日在12:44

对我来说,在OS X(10.10.3)上,第一个创建了后缀-e的备份文件。不好。第二个是唯一在Ubuntu和OS X之间一直对我有用的东西。尽管我不希望备份文件,所以删除后必须立即运行rm命令。

–布伦丹
15年7月30日在1:34

第一行应重写为在10.10上可用的空间:sed -i''... => sed -i''...

–丹尼尔(Daniel Jomphe)
15年8月28日在20:36



@DanielJomphe但添加此空间在GNU sed上不起作用

– Brice
16年2月12日在16:17

@marcin第一个在OSX 10.11.2上也适用于我。唯一的事情是它将创建一个备份文件,此文件随后需要删除。第二个看起来更好,因为我们以后不必弄清楚文件名了。

–vikas027
17-2-26在3:06



#4 楼

在Mac中遇到了相同的问题,并使用brew解决了问题:

brew install gnu-sed


,并用作

gsed SED_COMMAND


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

alias sed=gsed


评论


您为什么给出与Ohad Kravchick完全相同的答案?

– gniourf_gniourf
17年1月1日于15:55



像这样设置别名不是一个好主意

– SantaXL
19-10-2在0:24

代替别名(按照相应的brew页面中的建议),将其添加到路径:PATH =“ $(brew --prefix)/ opt / gnu-sed / libexec / gnubin:$ PATH”

– y.luis
19年11月25日在16:10

#5 楼

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

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

评论


..或如果您使用自制软件,则安装gnu-sed

– Sudar
2012年12月10日上午10:17

感谢@Sudar,请多加指点!

–安德鲁·斯旺(Andrew Swan)
13年6月20日,0:53

#6 楼

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

评论


感谢您指出BSD的问题-但是我非常文盲,只需要快速修复命令即可-快速浏览一下人并没有告诉我任何事情

–雅林
2010-11-22 15:50

@Yarin-不,如果我快速浏览一下man sed,那也不会告诉您任何信息。尝试更长的时间。

–高性能标记
2010-11-22 15:58

大多数SO答案都埋在一个人的某个地方,但这就是SO忙碌的人,他们需要聪明人的答案

–雅林
2010-11-22在16:05

#7 楼

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

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


通常,在复杂项目中使用不带sedfind时效率较低。

评论


-exec非常好!我只是想知道到底是否需要斜线

–刘烨
16-2-29在20:06

@YeLiu:没有\,当我尝试这样被外壳解释

– serv-inc
17年11月21日在13:28



#8 楼

我创建了一个函数来处理MacOS(在MacOS 10.12上测试)与其他OS之间的sed差异:

OS=`uname`
# $(replace_in_file pattern file)
function replace_in_file() {
    if [ "$OS" = 'Darwin' ]; then
        # for MacOS
        sed -i '' -e "" ""
    else
        # for Linux and Windows
        sed -i'' -e "" ""
    fi
}


用法:

$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")


其中:

,是一个分隔符

's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"','是模式

"./mysql/.env"是文件的路径

#9 楼

这是将环境变量应用于模板文件的方法(无需备份)。

1。使用{{FOO}}创建模板以供以后替换。

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


2.。将{{FOO}}替换为FOO变量,然后输出到新的foo.conf文件中。

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


同时运行macOS 10.12.4和Ubuntu 14.04.5

#10 楼

这是bash脚本中的一个选项:
#!/bin/bash

GO_OS=${GO_OS:-"linux"}

function detect_os {
    # Detect the OS name
    case "$(uname -s)" in
      Darwin)
        host_os=darwin
        ;;
      Linux)
        host_os=linux
        ;;
      *)
        echo "Unsupported host OS. Must be Linux or Mac OS X." >&2
        exit 1
        ;;
    esac

   GO_OS="${host_os}"
}

detect_os

if [ "${GO_OS}" == "darwin" ]; then
    sed -i '' -e ...
else
    sed -i -e ...
fi


评论


您能以某种方式仅调节gsed的存在并将其用作变量吗?

–石油猎人
8月11日下午5:41

#11 楼

正如其他答案所表明的,没有一种方法可以在不制作备份文件的情况下跨OS X和Linux移植使用sed。因此,我改用这种Ruby单一代码来做到这一点:

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


就我而言,我需要从rake任务(即在Ruby内部)中调用它脚本),因此我使用了这种附加的引文级别:

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


#12 楼

sed调用sed的想法,我做./bin/sed
,这是我~/project/bin/sed中的包装器脚本
#!/bin/bash

if [[ "$OSTYPE" == "darwin"* ]]; then
  exec "gsed" "$@"
else
  exec "sed" "$@"
fi

不要忘了chmod 755包装器脚本。

评论


假设您已经在Mac上预先完成了gnu-sed的brew install

–美国忍者战士
12月19日15:42

#13 楼

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

在带gnu sed的BSD和Linux上均可工作

评论


这会在Linux上创建另一个文件名并附加e

– Brice
16年2月12日在16:13



坏了,最好将其删除。

–索林
16-11-16在11:56

它适用于Mac和Linux。此解决方案有什么问题?

–伊斯兰Azab
19年5月13日在15:05

不,它在Mac BSD Sed上不起作用-它将创建一个备份文件,并在文件名中添加“ e”。

–Jesper Grann Laursen
19年9月6日在8:17