だから、この質問には答えがありましたが、最終的にはかなり前にほとんどすべてのケースでこれを正しく行う方法を直観的に考えましたが、ごく最近、標準のテキストでその理解をかなり具体的にすることができました。それは実際、かなり簡単にそこに述べられています-私はただそれを何度も見落としていたと思います。
テキストの関連部分はすべて見出しの下にあります...
の編集コマンドsed
:
引数テキストは、1行以上で構成されます。\n
テキストに埋め込まれた各ewlineの前には\
バックスラッシュが必要です。テキスト内の他のバックスラッシュは削除され、次の文字は文字どおりに扱われます。
r
そしてw
、コマンド動詞、及びw
にフラグs
コマンド、任意取るRFILE(又はwfileの)パラメータ、一つ以上により文字またはフラグ動詞コマンドから分離します<blank>s
。実装は拡張としてゼロ分離を許可する場合があります。
コマンド動詞以外の{
、a
、b
、c
、i
、r
、t
、w
、:
、と#
続くことができ;
セミコロン、オプション<blank>s
、および他のコマンド動詞。ただし、s
コマンドの動詞がw
フラグとともに使用される場合、この方法で別のコマンドを使用すると、未定義の結果が生成されます。
...に...
そして最後に...
オペランド:
- script-編集コマンドのスクリプトとして使用される文字列。アプリケーションは、テキストファイルの制限に違反するスクリプトを提示することはできません。ただし、最終的な文字が必須である必要はありません
\n
。
したがって、完全にそれを取るとき、(s d sub d repl d flag
たとえば)事前に定義された区切り文字なしで任意のパラメーターがオプションで後に続くコマンドは、エスケープされていない\n
ewlineで区切る必要があります。
その議論の余地で;
ある事前定義された区切り文字が、その場合には使用;
のいずれかについて[aic]
別個であること、に使用されるパーサーから-コマンドは、別のパーサは、特にこれらの3つのコマンドの実装に含まれることを必要とする[:brw]
、たとえば。または、テキストパラメータ内でバックスラッシュをエスケープすることを実装に要求する必要が;
あり、それ以降はさらに複雑になります。
場合は、私が書いていたsed
私は準拠しており、効率的であることが望まれを、そして私は、そのような別のパーサを書きません、私は期待して-その多分除い[aic]
べき世代の構文エラーをすぐに続いていない場合\n
ewline。しかし、それは単純なトークン化の問題です-終了区切り文字の場合は、一般に問題の多いものです。私はそれを次のように書くでしょう:
sed -e w\ file\\ -e one -e '...;and more commands'
...そして...
sed -e a\\ -e appended\\ -e text -e '...;and more commands'
...最初のものが次の名前のファイルを作成して書き込むという点で、非常に似た動作をします:
file
one
... 2番目は、出力の現在の行にテキストブロックを追加します...
appended
text
...両方がパラメータの同じ解析コードを共有するためです。
そして{ ... }
、$!
問題に関して-まあ、私はそこから外れていました。アドレスが先行する単一のコマンドは機能ではなく、単にアドレス指定されたコマンドです。コメントとラベル定義を除き、ほとんどすべてのコマンド({
関数定義 を含む)}
は、受け入れる/one/
か/one/,/two/
アドレス指定するように指定されています。また、アドレスは行番号または通常のエクスプレスのいずれかであり、で否定できます。すべての...#
:
!
$!d
/address/s/ub/stitution/
5!y/d/c/
... ;
標準に従って1つ以上のコマンドを続けることができますが、単一のアドレスにさらにコマンドが必要であり、各コマンドの実行後にそのアドレスを再評価しない場合は、次のような{
関数}
を使用する必要があります:
/address/{ s//replace addressed pattern/
s/do other conditional/substitutions/
s/in the same context/without/
s/reevaluating/address/
}
... {
同じ行で閉じが続くことはできず、行の先頭を除い}
て閉じる}
ことはできません。ただし、含まれているコマンドの後に\n
改行を続けてはならない場合は、関数内に含める必要もありません。したがって、上記のすべてのs///
裏付け、さらに閉じ}
括弧さえも、;
セミコロンと追加のコマンドを移植可能に続けることができます。
私は\n
ewline区切り文字について話し続けていますが、質問は代わりに-e
xpressionステートメントについてです、私は知っています。しかし、2つは実際にはまったく同じであり、重要な関係は、スクリプトがリテラルのコマンドライン引数またはのいずれかのファイルで-[ef]
あり、両方がテキストファイルとして解釈されることです(これは、\n
ewline)しかし、どちらも実際にはewlineで終わる必要はありません\n
。これによって私はreasonblyできる(Iの希望)と推論\0NUL
区切りの引数が終わる暗示\n
すべての呼び出しの引数を取得するようewlineを、と)少なくとも\0NUL
とにかく区切り文字を、その後、いずれかの罰金を動作するはずです。
実際、実際には、\
バックスラッシュでエスケープされた改行が標準で指定されている場合を除いて、あらゆる場合に必要であることがわかりました。
sed -e ... -e '...\' -e '...'
...同様に動作します。そして、すべての場合-繰り返しますが、実際には- \n
エスケープされていないユーラインが必要な場合...
sed -e '...' -e '...'
...私のためにも働いています。上記で言及した1つの例外は...
sed -e 's/.../...\' -e '.../'
...これは私のテストのどの実装でも機能しません。これはテキストファイルの要件とデリミタがs///
付いているという事実にフォールバックしているため、単一のステートメントが\0NUL
デリミタ付きの引数にまたがる理由はありません。
したがって、結論として、ここにいくつかの種類のsed
コマンドを書くためのポータブルな方法の短い要約を示します。
のいずれか[aic]
:
...commands;[aic]\
text embedded newline\
delimiting newline
...more;commands...
...または...
sed -e '...commands;[aic]\' -e 'text embedded newline\' -e 'delimiting newline' -e '.;.;.'
いずれかの[:rwtb]
場所のパラメータがあり、オプション (除くすべてのため:
)が、区切り\n
ewlineはありません。注私は複数行しようとする理由はありませんでしたことをラベルに使用されるなどのパラメータを[:tb]
、それw
書くとは/ r
で複数行にeading [RW]ファイルのパラメータは、通常で質問せずに受け入れられているsed
私が埋め込まれている限り、テストしているの\n
ewlineワット/エスケープされ\
、バックスラッシュ。それでも、標準では、ラベルおよび[rw] fileパラメータをテキストと同じように解析する必要があることを直接指定していません。パラメータであり、\n
それらを区切る場合を除いて、最初の2つに関するewlinesについては言及していません。
...commands;[:trwb] parameter
...more;commands...
...または...
sed -e '[:trwb] parameter' -e '...'
...ここで、<space>
上記はオプションです[:tb]
。
そして最後...
...;address[!]{ ...function;commands...
};...more;commands....
...または...
sed -e '...;address[!]{ ...function;commands...' -e '};...more;commands...'
...上記のコマンド(を除く:
)は、少なくとも1つのアドレスを受け入れ、/
正規表現/
または行番号のいずれかであり、で否定される!
場合がありますが、アドレスの単一評価に複数のコマンドが必要な場合は、中括弧を区切る{
関数コンテキスト}
を使用する必要があります。関数には、\n
ewlineで区切られた複数のコマンドを含めることもできますが、各コマンドは中括弧で区切る必要があります。
そして、それが移植可能なsed
スクリプトの書き方です。
b;n;:b
、";n;:b"
歴史的およびPOSIXのsedで呼び出されるラベルに分岐しています(GNU sedはその点ではありません)。