具有多个搜索/替换的 ed(1) 脚本

具有多个搜索/替换的 ed(1) 脚本

正在研究一个问题代码高尔夫网站,尝试进行简单的文本替换。

  • 给定一个文件coin.txt包含 1 个单词,heads或者tails
  • 我有一个ed脚本flip.ed如下:
s/heads/1/n\
s/tails/-1/n\
wq
.
  • 然后我从终端(macos、zsh)执行它,如下所示:(每“艾德·掌握”,第 111 章)
[~/高尔夫/ed]λed coin.txt < 翻转.ed;猫币.txt  
6
尾巴

预计脚本会更改tails-1.我从 BSD 和 GNU ed(/bin/ed以及/usr/local/bin/ged和 TIO.run )得到了同样的问题。两者似乎都无法执行多次替换。

这是一个TIO.run 上的示例,我认为它正在运行 GNU 版本。

ed我的脚本有问题吗?还是强大中的一个buged??

更新

一个解决方案,礼貌@ed1conf在推特上。使用g前缀仅在匹配行上进行替换,从而避免了破坏我原始脚本的错误。 在线尝试一下!

g/heads/s//1/
g/tails/s//-1/
wq
.

答案1

您可以执行此操作,但无法通过重定向或常规文件发送命令。

来自GNU 编辑在线手册:

当发生错误时,如果 ed 的输入来自常规文件或此处文档,则退出,否则打印“?”并返回命令模式。

两个命令之一将会失败,因为文件中的单词无法匹配两种模式,因此ed会退出 - 无论是在第 1 行,因为它不匹配,还是在第 2 行,因为它不匹配不匹配(因此在保存更改的文件之前退出)。

这些命令可以通过标准输入工作(减去反斜杠和后缀):

printf '%s\n' 's/heads/1/' 's/tails/-1/' 'wq' | ed -s coin.txt

?由于s/heads/1/失败(您可以重定向),您将收到stderr,但替换全部按预期发生。

请注意,我删除了尾随.命令,因为该q命令足以退出ed


解决方法,发布者ed(1) Twitter 上的会议, 是:

g/heads/s//1/
g/tails/s//-1/
wq

或者,该部分中没有缩写s///

g/heads/s/heads/1/
g/tails/s/tails/-1/
wq

这些变体之所以有效,是因为g即使不执行替换,命令也不会失败。

答案2

有了sed,你可以这样做

sed 's/heads/tails/;t;s/tails/heads/'

在 中ed,该t命令是一个完全不同的命令,并且不会“如果最近的替换执行某些操作则分支”。

使用GNU ed,你可以做

printf '%s\n' '1s/heads/T/' '1s/tails/H/' '1s/H/heads/' '1s/T/tails/' 'wq' | ed -s coin.txt

进行翻转,但它可能无法在 BSD 中工作,ed因为命令的处理在第一个不匹配的替换处停止,因为

当输入脚本中遇到错误时,或者检测到错误是由于文件中存在(不)存在的数据或由于外部条件(例如读取或写入错误)而导致的错误时:

  • 如果标准输入是终端设备文件,则应刷新所有输入,并读取新命令。

  • 如果标准输入是常规文件,ed则应以非零退出状态终止。

(那是来自POSIX 标准

运行此脚本时从 GNU 收到的错误ed是“不匹配”错误(如果您H首先在脚本中插入命令,则可见),并且可以安全地忽略。

相关内容