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

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

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1043  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   41  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   35  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   32  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   34  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用