sed 就地标志,适用于 Mac(BSD)和 Linux [关闭]

2024-09-30 15:23:00
admin
原创
97
摘要:问题描述:有没有一种sed无需备份即可在 Linux 和 Mac 上进行 todo 就地编辑的调用?虽然sedOS X 附带的 BSD 似乎需要sed -i '' …,但 GNU sedLinux 发行版通常会将引号解释为空输入文件名(而不是备份扩展名),而需要sed -i...

问题描述:

有没有一种sed无需备份即可在 Linux 和 Mac 上进行 todo 就地编辑的调用?虽然sedOS X 附带的 BSD 似乎需要sed -i '' …,但 GNU sedLinux 发行版通常会将引号解释为空输入文件名(而不是备份扩展名),而需要sed -i …

是否存在适用于这两种版本的命令行语法,以便我可以在两个系统上使用相同的脚本?


解决方案 1:

如果您确实只想使用sed -i“简单”的方法,那么下面的方法在 GNU 和 BSD/Mac 上都有效sed

sed -i.bak 's/foo/bar/' filename

请注意缺少空格和点。

证明:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

显然,您可以直接删除这些.bak文件。

解决方案 2:

这在 GNU sed 上有效,但在 OS X 上无效:

sed -i -e 's/foo/bar/' target.file
sed -i'' -e 's/foo/bar/' target.file

这在 OS X 上有效,但在 GNU sed 上无效:

sed -i '' -e 's/foo/bar/' target.file

在 OS X 上

  • 无法使用sed -i -e,因为备份文件的扩展名将被设置为-e

  • 由于同样的原因不能使用——和sed -i'' -e之间需要一个空格。-i`''`

解决方案 3:

在 OSX 上时,我总是通过 Homebrew 安装 GNU sed 版本,以避免脚本出现问题,因为大多数脚本都是为 GNU sed 版本编写的。

brew install gnu-sed --with-default-names

那么你的 BSD sed 将被 GNU sed 取代。

或者,您也可以不使用默认名称进行安装,但是:

  • PATH安装后按指示更改gnu-sed

  • 请检查你的脚本以选择gsedsed取决于你的系统

解决方案 4:

正如Noufal Ibrahim所问,为什么不能使用 Perl?任何 Mac 都会有 Perl,而且很少有 Linux 或 BSD 发行版不在基本系统中包括某个版本的 Perl。唯一可能实际上缺少 Perl 的环境之一是 BusyBox(其工作方式与 GNU/Linux 类似-i,只是不能指定备份扩展)。

正如伊斯梅尔所建议的,

由于 perl 随处可用,因此我只需perl -pi -e s,foo,bar,g target.file

并且在几乎任何情况下,这似乎都是比脚本、别名或其他解决方法更好的解决方案,可以解决sed -iGNU/Linux 和 BSD/Mac 之间根本的不兼容性。

解决方案 5:

这是另一个可以在 Linux 和 macOS 上运行的版本,无需使用eval也无需删除备份文件。它使用 Bash 数组来存储sed参数,这比使用更简洁eval

# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac

# Expand the parameters in the actual call to "sed"
sed "${sedi[@]}" -e 's/foo/bar/' target.file

这不会创建备份文件,也不会创建带有附加引号的文件。

解决方案 6:

答:不是。

最初接受的答案实际上并没有满足要求(如评论中所述)。 (我在寻找file-e目录中“随机”出现的原因时找到了这个答案。)

显然没有办法sed -i在 MacOS 和 Linuces 上一致地工作。

我的建议是,不要使用 进行就地更新sed(这具有复杂的故障模式),而是生成新文件并随后重命名。换句话说:避免-i

解决方案 7:

没有办法让它工作。

一种方法是使用临时文件,例如:

TMP_FILE=`mktemp /tmp/config.XXXXXXXXXX`
sed -e "s/abc/def/" some/file > $TMP_FILE
mv $TMP_FILE some/file

这对两者都有效

解决方案 8:

-i选项不是POSIX Sed的一部分。更便携的方法是在 Ex 模式下使用 Vim:

ex -sc '%s/alfa/bravo/g' -c 'x' file
  1. -s静音模式

  2. -c运行命令

    1. %选择所有行

    2. s代替

    3. /<old>/<new>/

    4. g`old`替换行中所有出现的

  3. -c运行命令

    1. x保存并退出

|x原始答案使用了这样的管道,'%s/alfa/bravo/g|x'如果文件中不存在字符串,则会导致编辑器挂起:

Error detected while processing command line:
E486: Pattern not found: <old>

使用附加功能-c 'x'可以解决该问题。

大多数人都希望在 find 命令中找到它,因此这里有一个神奇的咒语:

find . \n  -type f \n  -exec ex -sc '%s/<old>/<new>/g' -c 'x' {} ;

PS:不要像我一样弄乱你的 git 文件夹:

find . \n  -path ./.git -prune -o \n  -type f \n  -exec ex -sc '%s/<old>/<new>/g' -c 'x' {} ;

解决方案 9:

史蒂夫鲍威尔的回答是相当正确的,查阅OSX和Linux(Ubuntu 12.04)上sed的MAN页面强调了两个操作系统之间“就地”sed使用的不兼容性。

JFYI,使用 Linux 版本的 sed 时,-i 和任何引号(表示空文件扩展名)之间不应该有空格,因此

sed Linux 手册页

#Linux
sed -i"" 

sed OSX 手册页

#OSX (notice the space after the '-i' argument)
sed -i "" 

我在脚本中通过在 bash 'if' 中使用别名命令和 ' uname ' 的 OS 名称输出解决了这个问题。在解释引号时,尝试将依赖于操作系统的命令字符串存储在变量中是碰运气的。为了扩展/使用脚本中定义的别名,必须使用' shopt -s expand_aliases '。shopt 的用法在此处处理。

解决方案 10:

适用于 GNU 系统和 OSX 的可移植脚本:

if [[ $(uname) == "Darwin" ]]; then
    SP=" " # Needed for portability with sed
fi

sed -i${SP}'' -e "s/foo/bar/g" -e "s/ping/pong/g" foobar.txt

解决方案 11:

如果您需要sed在脚本中执行就地操作bash,并且您不希望就地操作产生 .bkp 文件,并且您有办法检测操作系统(例如,使用ostype.sh),那么以下使用bashshell 内置的hackeval应该可以工作:

OSTYPE="$(bash ostype.sh)"

cat > myfile.txt <<"EOF"
1111
2222
EOF

if [ "$OSTYPE" == "osx" ]; then
  ISED='-i ""'
else # $OSTYPE == linux64
  ISED='-i""'
fi

eval sed $ISED 's/2222/bbbb/g' myfile.txt
ls 
# GNU and OSX: still only myfile.txt there

cat myfile.txt
# GNU and OSX: both print:
# 1111
# bbbb

# NOTE: 
# if you just use `sed $ISED 's/2222/bbbb/g' myfile.txt` without `eval`,
# then you will get a backup file with quotations in the file name, 
# - that is, `myfile.txt""`

解决方案 12:

问题是它sed是一个编辑器,因此就地编辑是一个非 POSIX 扩展,每个人可能以不同的方式实现它。这意味着对于就地编辑,您应该使用ed以获得最佳的可移植性。例如

ed -s foobar.txt <<<$',s/foo/bar/g
w'

另请参阅https://wiki.bash-hackers.org/howto/edit-ed

解决方案 13:

在 macOs 上,你可以使用-earg 代替-i(在 Linux 上)sed -e 's/foo/ar/' src_path > source_path

示例文件内容:
python3 /tools/check.py -=some-arg=somevalue

cmd 后的结果sed -e 's//tools/check.py//tools/check.pyc/' example.sh > result.sh

python3 /tools/check.pyc -=some-arg=somevalue

另外,> source_path您不会在标准输出中看到结果。

解决方案 14:

以下内容在 Linux 和 OS X 上对我有用:

sed -i' ' <expr> <file>

f例如包含以下文件aaabbaaba

sed -i' ' 's/b/c/g' f

在 Linux 和 Mac 上均有效aaaccaaca。请注意,引号内的字符串包含空格,而和字符串之间没有空格-i。单引号或双引号均可使用。

在 Linux 上我使用的bash是 Ubuntu 14.04.4 下的 4.3.11 版本,在 Mac 上我使用的是 OS X 10.11.4 El Capitan(Darwin 15.4.0)下的 3.2.57 版本。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用