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

2024-09-30 15:23:00
admin
原创
256
摘要:问题描述:有没有一种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 版本。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2379  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1510  
  PLM(产品生命周期管理)系统在企业项目管理中扮演着至关重要的角色,它能够整合产品从概念设计到退役的全流程信息,提升协同效率,降低成本。然而,项目范围蔓延是项目管理过程中常见且棘手的问题,在PLM系统环境下也不例外。范围蔓延可能导致项目进度延迟、成本超支、质量下降等一系列不良后果,严重影响项目的成功交付。因此,如何在P...
plm项目经理是做什么   16  
  PLM(产品生命周期管理)系统在现代企业的产品研发与管理过程中扮演着至关重要的角色。它不仅仅是一个管理产品数据的工具,更能在利益相关者分析以及沟通矩阵设计方面提供强大的支持。通过合理运用PLM系统,企业能够更好地识别、理解和管理与产品相关的各类利益相关者,构建高效的沟通机制,从而提升产品开发的效率与质量,增强企业的市场...
plm是什么   20  
  PLM(产品生命周期管理)项目管理对于企业产品的全生命周期规划、执行与监控至关重要。在项目推进过程中,监控进度偏差是确保项目按时、按质量完成的关键环节。五维健康检查指标体系为有效监控PLM项目进度偏差提供了全面且系统的方法,涵盖了项目的多个关键维度,有助于及时发现问题并采取针对性措施。需求维度:精准把握项目基石需求维度...
plm项目管理软件   18  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用