ポータブルsed -e…dbまたは!b?


12

では、この編集 ステファンChazelas POSIXifies (再び)私がsed挿入して書式設定-eXPRESSIONブレークと他の-eXPRESSION文を。今、私は単にコメントでなぜ彼に尋ねるかもしれませんが、その答えのリビジョン番号はすでに18であり、以前のほとんどはすでに同様の景品のおかげでした(削除されたコメントを見ることができるなら、あなたは何を知っているでしょうつまり)。また、より一般的に役立つ方法でこれを表現する理由を十分理解していると思います。だからここに期待しています...

一般的sed -eには、可能であれば合計xpressionsを1 に維持することを好みますが、特に差がa およびanに過ぎない場合は、可能な限り仕様に準拠することを優先します。しかし、なぜそうすべき理解していない場合、これを行うことはできません。ここに私の理解の現在の状態の簡単な要約があります:<space>-e

  • ' -e 'ブレークが移植性のためで立つことができるsedのスクリプト\nでewlineブレークsedコマンドラインステートメント... 私は理由について明らかにあいまいです

  • sed {関数内の右中括弧の}前には、\nここに記載されているようにewlineブレークが必要です。

    • <right-brace>前にa <newline>を付け、<blank>文字の前または後に指定できます。
  • \newlineブレークは、同様に...のいずれかの使用、次の要求されabcirtw、または:

しかし、{関数}定義が!not演算子にどのように関係するのか明確にはわかりません。仕様の状態で否定演算子について私が見つけた唯一の言及:

  • 関数の前に1つ以上の!文字を置くことができます。この場合、アドレスがパターンスペースを選択しない場合、関数が適用されます。

これは、aの使用!{中括弧を意味することを意味します}か?$!コマンドは何ですか-同様に' -e 'ブレークで区切る必要がありますか?Stéphaneが最近POSIXで答えを出したとき、これは対処されたものでしたか?

私はそれが!否定演算子であるかb、彼が彼の編集で対処する牧場ステートメントであると思う-または多分一度に両方である-しかし、私は知りませんし、好きです。それが牧場の声明だけであるなら私はその代わりにやると休憩の必要性をなくすと信じていますが、POSIX化された3 つの答えを危険にさらす前に私はむしろ確信しています。手伝ってくれますか?bd' -e '

私は結局それ危険にさらしましたが、大きな確実性はありませんでした...


ではb;n;:b";n;:b"歴史的およびPOSIXのsedで呼び出されるラベルに分岐しています(GNU sedはその点ではありません)。
ステファンシャゼル14

@StéphaneChazelas-役に立た:ない-あなたは数ヶ月前にその家を運転した。ただし、2番目のsedコマンドが同様にPOSIX化された理由は完全には理解できません。
mikeserv 14

1
いずれにせよ、POSIXの仕様sedは私には非常に明確ではありません。過去に何度か説明を求めてきましたが、結果として更新されたとは思いません。良いテストは、家宝ツールチェスト(Solarisのもので、オリジナルから派生し、POSIX仕様の大部分はこれに基づいています)を試すことです。
ステファンシャゼル14

1
@syntaxerror-私はそれがまったくそうではないと信じています。仕様を読むと、s///ubstitutionがaとの連鎖を受け入れる仕様になっていることがわかります。改行で区切らなければならないコマンドの周りがぼやけて-eおり、その場合にどのように対応できるか-少なくとも私にとってはそうです。sedしかし、それらをかなり互換的に解釈しないものについてはつまずきません。
mikeserv 14

1
@syntaxerror-気に入っていますが;、改行の前は必要ないことを知っておく必要があります-改行は問題ありません。正直なところ、あなたは可能性なしで行う-eと、すべて完全に、ちょうどのようなファイルの書き込み#!/bin/sedまたはその代わりに区切られ、このような区切り文字を必要としないもの-改行の各コマンドでは;。ものやる改行を必要とするが、通常、任意の入力取るものです- :のようにそれらを参照するラベル名とコマンドをbtまたは閉じ}機能、またはのためのカーリーをrEADとwファイル名の引数を取る儀式。それらはすべて移植可能に続く必要があります\n
mikeserv

回答:


4

だから、この質問には答えがありましたが、最終的にはかなり前にほとんどすべてのケースでこれを正しく行う方法を直観的に考えましたが、ごく最近、標準のテキストでその理解をかなり具体的にすることができました。それは実際、かなり簡単にそこに述べられています-私はただそれを何度も見落としていたと思います。

テキストの関連部分はすべて見出しの下にあります...

  • の編集コマンドsed

    • 引数テキストは、1行以上で構成されます\nテキストに埋め込まれた各ewlineの前には\バックスラッシュが必要です。テキスト内の他のバックスラッシュは削除され、次の文字は文字どおりに扱われます。

    • rそしてw、コマンド動詞、及びwにフラグsコマンド、任意取るRFILE(又はwfileの)パラメータ、一つ以上により文字またはフラグ動詞コマンドから分離します<blank>s。実装は拡張としてゼロ分離を許可する場合があります。

    • コマンド動詞以外の{abcirtw:、と#続くことができ;セミコロン、オプション<blank>s、および他のコマンド動詞。ただし、sコマンドの動詞がwフラグとともに使用される場合、この方法で別のコマンドを使用すると、未定義の結果が生成されます。

...に...

  • オプション:複数-e-fオプションを指定することができます。すべてのコマンドは、起源に関係なく、指定された順序でスクリプトに追加されます。

    • -e script-編集コマンドのスクリプトの最後に、スクリプトオプション引数で指定された編集コマンドを追加します。スクリプトのオプション引数は、同じ特性を有するものとし、スクリプトに記述オペランド、オペランドのセクションを。

    • -f script_file-ファイルscript_fileの編集コマンドをスクリプトの最後に追加します。

そして最後に...

  • オペランド:

    • script-編集コマンドのスクリプトとして使用される文字列。アプリケーションは、テキストファイルの制限に違反するスクリプトを提示することはできません。ただし、最終的な文字が必須である必要はありません\n

したがって、完全にそれを取るとき、s d sub d repl d flagたとえば)事前に定義された区切り文字なしで任意のパラメーターがオプションで後に続くコマンドは、エスケープされていない\newlineで区切る必要があります。

その議論の余地で; ある事前定義された区切り文字が、その場合には使用;のいずれかについて[aic]別個であること、に使用されるパーサーから-コマンドは、別のパーサは、特にこれらの3つのコマンドの実装に含まれることを必要とする[:brw]、たとえば。または、テキストパラメータ内でバックスラッシュをエスケープすることを実装に要求する必要が; あり、それ以降はさらに複雑になります。

場合は、私が書いていたsed私は準拠しており、効率的であることが望まれを、そして私は、そのような別のパーサを書きません、私は期待して-その多分除い[aic]べき世代の構文エラーをすぐに続いていない場合\newline。しかし、それは単純なトークン化の問題です-終了区切り文字の場合は、一般に問題の多いものです。私はそれを次のように書くでしょう:

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///裏付け、さらに閉じ}括弧さえも、;セミコロンと追加のコマンドを移植可能に続けることができます。

私は\newline区切り文字について話し続けていますが、質問は代わりに-expressionステートメントについてです、私は知っています。しかし、2つは実際にはまったく同じであり、重要な関係は、スクリプトがリテラルのコマンドライン引数またはのいずれかのファイルで-[ef]あり、両方がテキストファイルとして解釈されることです(これは、\newline)しかし、どちらも実際には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]場所のパラメータがあり、オプション (除くすべてのため:が、区切り\newlineはありません。注私は複数行しようとする理由はありませんでしたことをラベルに使用されるなどのパラメータを[:tb]、それw書くとは/ rで複数行にeading [RW]ファイルのパラメータは、通常で質問せずに受け入れられているsed私が埋め込まれている限り、テストしているの\newlineワット/エスケープされ\、バックスラッシュ。それでも、標準では、ラベルおよび[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つのアドレスを受け入れ、/正規表現/または行番号のいずれかであり、で否定される!場合がありますがアドレスの単一評価に複数のコマンドが必要な場合は、中括弧を区切る{関数コンテキスト}を使用する必要があります。関数には、\newlineで区切られた複数のコマンドを含めることもできますが、各コマンドは中括弧で区切る必要があります。

そして、それが移植可能なsedスクリプトの書き方です。


2
なぜあなたはあなた自身の答えを受け入れませんか?
フィリポス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.