我已成功使用以下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' *
答案 0 :(得分:332)
如果您使用-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
备份sed -i'' -e ...
- 在OS X 10.6上不起作用,但适用于10.9 + sed -i '' -e ...
- 没有使用GNU 注意鉴于没有sed命令在所有平台上运行,您可以尝试使用其他命令来实现相同的结果。
,例如perl -i -pe's/old_link/new_link/g' *
答案 1 :(得分:47)
我相信OS X时使用-i对备份文件的扩展名为 required 。尝试:
sed -i .bak 's/hello/gbye/g' *
使用GNU sed
,扩展名为可选。
答案 2 :(得分:46)
这适用于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必备)
答案 3 :(得分:23)
在Mac中遇到同样的问题并用brew
解决了它:
brew install gnu-sed
并用作
gsed SED_COMMAND
您也可以将sed
设置为gsed
的别名(如果需要):
alias sed=gsed
答案 4 :(得分:16)
或者,您可以在Mac中安装GNU版本的sed,名为gsed,并使用标准Linux语法进行使用。
为此,请运行gsed
,使用端口安装sudo port install gsed
(如果您没有端口,请通过http://www.macports.org/获取)。然后,您可以运行sed -i 's/old_link/new_link/g' *
答案 5 :(得分:8)
你的Mac确实运行了一个BASH shell,但这更像是你正在处理的sed实现的问题。在Mac上,sed来自BSD,与您在典型Linux机器上可能找到的sed略有不同。我建议你man sed
。
答案 6 :(得分:8)
Sinetris的答案是正确的,但我使用find
命令来更具体地说明我想要更改的文件。通常这应该工作(在osx /bin/bash
上测试):
find . -name "*.smth" -exec sed -i '' 's/text1/text2/g' {} \;
一般情况下,在复杂项目中使用sed
而不使用find
效率较低。
答案 7 :(得分:1)
以下是如何将环境变量应用于模板文件(无需备份)。
echo "Hello {{FOO}}" > foo.conf.tmpl
FOO="world" && sed -e "s/{{FOO}}/$FOO/g" foo.conf.tmpl > foo.conf
同时使用 macOS 10.12.4 和 Ubuntu 14.04.5
答案 8 :(得分:1)
这是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
答案 9 :(得分:1)
除了用 sed
调用 sed,我还用 ./bin/sed
这是我的 ~/project/bin/sed
#!/bin/bash
if [[ "$OSTYPE" == "darwin"* ]]; then
exec "gsed" "$@"
else
exec "sed" "$@"
fi
不要忘记chmod 755
包装脚本。
答案 10 :(得分:0)
sed -ie 's/old_link/new_link/g' *
适用于BSD和& Linux的
答案 11 :(得分:0)
正如其他答案所示,没有办法在不制作备份文件的情况下在OS X和Linux上移植使用sed。所以,我改为使用这个Ruby单行代码来执行此操作:
ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml
在我的情况下,我需要从rake
任务(即在Ruby脚本中)调用它,所以我使用了这个额外的引用级别:
sh %q{ruby -pi -e "sub(/ $/, '')" ./config/locales/*.yml}
答案 12 :(得分:0)
我创建了一个函数来处理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 "$1" "$2"
else
# for Linux and Windows
sed -i'' -e "$1" "$2"
fi
}
用法:
$(replace_in_file 's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"',' "./mysql/.env")
位置:
,
是分母
's,MASTER_HOST.*,MASTER_HOST='"$MASTER_IP"','
是模式
"./mysql/.env"
是文件的路径