web-dev-qa-db-ja.com

複数の検索/置換を伴うed(1)スクリプト

codegolf.se の質問に取り組んでおり、単純なテキスト置換を試みています。

  • headsまたはtailsのいずれか1つの単語を含むファイルcoin.txtが与えられます
  • 次のようなedスクリプトflip.edがあります。
s/heads/1/n\
s/tails/-1/n\
wq
.
  • 次に、ターミナル(macos、zsh)から次のように実行します:(per " Ed Mastery "、Chapter 111)
[〜/ Golf/ed]λ ed coin.txt <flip.ed; cat coin.txt 
 6 
?
 tails 

スクリプトがtails-1に変更することを期待しました。 BSDとGNU ed(/bin/ed and /usr/local/bin/ged、さらに言えばTIO.run)からも同じ問題が発生します。どちらも、複数の置換を実行できないようです。

これが TIO.runの例 、実行中だと思いますGNU ed。

edスクリプトに問題はありますか?それとも、強力なedのバグですか?

更新

Twitterの @ ed1conf の好意による解決策。 gプレフィックスを使用して、一致する行でのみ置換を行うため、元のスクリプトを壊すエラーを回避できます。 オンラインでお試しください!

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

これは可能ですが、リダイレクトまたは通常のファイルを介してコマンドを送信することはできません。

GNU edオンラインマニュアル から:

エラーが発生した場合、edの入力が通常のファイルまたはヒアドキュメントからのものである場合は終了し、それ以外の場合は「?」を出力します。コマンドモードに戻ります。

ファイル内のWordが両方のパターンに一致できないため、2つのコマンドのいずれかが失敗し、edが終了します。1行目が一致しないため、または2行目がitが一致しません(したがって、変更されたファイルが保存される前に終了します)。

コマンドは、stdinを介して機能します(バックスラッシュとサフィックスを除く)。

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

?が失敗したため(リダイレクトできます)、stderrにs/heads/1/を取得しますが、置換はすべて期待どおりに行われます。

qコマンドはedを終了するのに十分なので、末尾の.コマンドを削除したことに注意してください。


ed(1)Conference on Twitter によって投稿された回避策は次のとおりです。

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

または、s///部分に省略形がない場合:

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

これらのバリエーションは、置換が実行されなくてもgコマンドが失敗しないために機能します。

2
Jeff Schaller

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コマンドを挿入すると表示されます)。無視しても問題ありません。

1
Kusalananda