OSXのsedは特定の行に挿入されます。

OSXのsedは特定の行に挿入されます。

だから、しばらくLinuxでは「sed」を使ってきましたが、OSXでは「POSIX sed」と「GNU sed」の間に微妙な違いが多く、使用するのに少し難しかったです。現在、特定の行番号の後にテキスト行を挿入する方法が困難です。 (この場合は4行目)

Linuxでは、次のようにします。

sed --in-place "4 a\  mode '0755'" file.txt

そのため、OSXでは次のことを試しました。

sed -i "" "4 a\ mode '0755'" file.txt

ただし、これは「コマンドの終わりに\の後に追加の文字」エラーが発生し続けます。ここで何が起こっているのかというアイデアはありますか?私はタイプミスを出しましたか?それとも私が理解していないsedバージョンの間に別の違いがありますか?

答え1

厳密に言えば、POSIX仕様sedその後、梱包する必要がありますa\

[1addr]a\
text

前述のように標準出力にテキストを書き込みます。

これにより、気の利いた言葉を書くのは少し痛いです。おそらく、次の理由からです。GNU拡張aiおよびコマンドでc

GNU 拡張として、a改行と改行の間に一連の空白以外のものがある場合、次\の空白ではなく最初の文字で始まるテキストaテキスト詰まった。 (これは1行の追加スクリプトの作成を簡単にすることができます。)この拡張はiコマンドと一緒に使用することもできますc

したがって、構文と互換性を持たせるには、構文のsed後に改行文字を追加する必要がありますa\。最も簡単な方法は、引用した改行文字を挿入することです。

$ sed -e 'a\
> text'

(シェルプロンプトはどこに$あり、どこにありますか?)>痛みをbash感じたら[1]$' 'Cスタイルのエスケープを挿入する引用構文なので、単に使用してください。

sed -e 'a\'$'\n''text'

[1] バージョン 2.0 (1996) および ksh93 (該当するソース) 以降、zsh(3.1.5+)、mksh(r39b+)、および一部の Almquist シェル派生物 (例: FreeBSD 9+ の /bin/sh)

答え2

で述べたようにこの回答i、などのsedコマンドを使用するときは、a複数の句を使用すると便利です-e "..."。これらの各節は改行文字で区切られていることが理解される。そうでなければ、iコマンドはaインラインsedスクリプトで使用するのが難しいです(これらは、複数行のsedスクリプトファイルで使用するように設計されていますsed -f file ...)。追加するテキスト行を-e区切るために、句の最後に導入された暗黙の改行文字を使用できないようです。a\ただし、追加したいテキスト行を終了するために使用できます。

この特別なケースでは、必要な操作を実際に-e ...1つの句で実行できます。aコマンドを正しく使用してください。 POSIX規格によれば、a\に改行文字が続く必要があり、その後に次の行の残りの部分が挿入されます(-e改行文字または句の終わりが表示されるまで)。だからあなたはこれを行うことができます:

sed -i "" -e $'4 a\\\n'"mode '0755'" file.txt

答え3

Perlは、プラットフォーム依存のGNU、非GNU、「排他的な」特性のために困難を経験しません。次のことができます。

perl -ni.old -e 'print;if ($.==4) {print "mode 0755\n"}' file

この-nオプションは、入力ファイルの各行を読み取るループを作成します。いとこ-p(ここでは使用されていません)とは異なり、読み取るすべての行は自動的に印刷されません。-i内部交換を呼び出します。-i(たとえば、「.old」)パラメータは削除または変更できます。変更されていないファイルのバックアップを残します。-eスクリプトの開始を表示します。

$.行1から始まり、行番号を示します。したがって、コマンドラインはを読み、file行番号が4に等しい場合はその行を印刷し、注入する内容を印刷します。

sedPerlの根が、、、およびawkにあるという点を急いで付け加えます。Cしたがって、単純な置換などの構文は学習曲線がそれほど難しくありません。

答え4

簡単なデモ:

$ date | sed -E $'1i\\\nfoo\n'
foo
Thu Aug  6 07:09:01 CDT 2020

これは$'...'エスケープシーケンスの拡張を強制するbashismです。これを使用するときは、文字列からテキストを取得するために使用する必要があります\\\

関連情報