正在研究一个问题代码高尔夫网站,尝试进行简单的文本替换。
- 给定一个文件
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
首先在脚本中插入命令,则可见),并且可以安全地忽略。