Grepping、awking、sedding、およびパイプラインはコマンドラインまたはシェルスクリプト(通称フィルターこれから)。
デフォルトでは、「標準」Unix CLIプログラムとシェルが組み込まれています。注文するこれから)フィルタが正しく機能するためには、各フィルタステップで正確に予想されるstdin、stdout、およびstderrの形式が必要です。以下では、一部のコマンドの正確な予測形式を、そのコマンドのAPIと呼びます。
Web開発の背景を持つ人として、私はこの種のデータ収集とデータ処理を技術的に関連付けます。Webスクレイピング- この技術は、データ表現に若干の変化があるたびに非常に不安定です。
現在の問題は Unix コマンド API の安定性に関連しています。
- Unixファミリーオペレーティングシステムのコマンドは、入力と出力の公式標準化に従いますか?
- 歴史的にいくつかの重要なコマンドを更新すると、そのコマンドの以前のバージョンで構築されたいくつかのフィルタの機能が中断されたことがありますか?
- Unixコマンドは時間が経つにつれて成熟し、いくつかのフィルタを破ることができるようにコマンドを変更することは決して不可能になりましたか?
- コマンドAPIの変更によってフィルタが壊れる可能性がある場合、開発者としてこの問題からフィルタを保護するにはどうすればよいですか?
答え1
POSIX 2008規格には、説明するセクションがあります。「シェルとユーティリティ」。一般的に言って、これに従うならば、スクリプトはサポートの中断の可能性を除いてかなり未来志向でなければなりませんが、これが一日の朝に発生することはほとんどないので、スクリプトを更新するのに十分な時間が必要です。
単一ユーティリティの出力形式がプラットフォームとバージョンによって大きく異なる場合、POSIX標準には、保証された予測可能な出力形式を指定する一般的または-p
呼ばれるオプションを含めることができます。-P
これの例は次のとおりです。time
便利、実装は非常に多様です。安定したAPI /出力フォーマットが必要な場合time -p
。
POSIX標準で扱われていないフィルタユーティリティを使用する必要がある場合は、Webスクレイピングを実行するときにリモートWeb開発者の手にかかっているかのように、デプロイパッケージャ/アップストリーム開発者の手にほとんど依存します。
答え2
私の経験に基づいて答えてみましょう。
コマンドは実際には正式な仕様に準拠していませんが、行中心のテキストを使用して生成するための要件に準拠しています。
もちろんです。 GNUユーティリティが事実上の標準になる前に、多くのベンダーが特に
ps
およびls
。これにより多くの痛みが発生しました。今日、HPだけが非常に奇妙なコマンドを提供しています。歴史的に、BSD(Berkeley Software Distribution)ユーティリティは過去と大きく異なりました。 POSIX仕様は過去とは異なりますが、現在は広く受け入れられています。Unixコマンドは確かに時間の経過とともに成熟しました。以前のバージョン用に書かれたいくつかのスクリプトを中断することはまだ不可能ではありません。テキストファイルのエンコーディングとしてUTF-8を使用する最近の傾向を考えてみましょう。この変更には、基本ユーティリティの変更が必要です。たとえば、
tr
過去には単純なテキストがほぼ常にASCII(またはそれに近い)なので、大文字と小文字は数値範囲を形成していました。 UTF-8ではもうそうではありません。したがって、tr
「大文字」または「英数字」などの項目を指定するために、他のコマンドラインオプションが許可されます。フィルタを「強化」する最良の方法の1つは、特定のテキストレイアウトに依存しないことです。たとえば、しないでください
cut -c10-24
。行の位置によって異なります。代わりにcut -f2
、タブで区切られた2番目のフィールドを削除するを使用してください。awk
デフォルトでは、入力行を $1、$2、$3... でスペースで区切ります。熱位置などの低レベルの概念ではなく、「フィールド」などの高レベルの概念を使用してください。また、正規表現を使用してください。sed
どちらawk
も正規表現を使用して、入力差に関係のない操作を実行できます。もう一つの秘訣は、フィルタが要求の厳しい形式で入力を処理することです。tr -cs '[a-zA-z0-9]' '[\n]'
句読点なしでテキストを1行に1単語に分割するために使用されます。この場合、入力テキストがどのように見えるかを気にする必要はありません。
答え3
まず、あなたの質問に対する非常に簡単な答えです。
- 入力/出力ルールの公式標準化:いいえ
- 出力変更による過去のダメージ:はい
- 将来のフィルターを壊すことは絶対に不可能です。いいえ
- 変化から自分自身を守る方法:保守的に行動する
「API」と言うときに使用される用語は、良いか悪いかにかかわらず、フィルタの入力/出力ルールが形式的であることを意味します。非常に広く(「非常に」を意味する)、簡単にフィルタリングできるデータの主な規則は次のとおりです。
- 各入力ラインは完全なレコードです。
- 各レコードでは、フィールドは既知の区切り文字で区切られます。
一般的な例は /etc/passwd 形式です。しかし、これらの基本的な規則は厳密に遵守されるよりもある程度違反することが多い。
- 複数行の入力形式を解析するための多くのフィルタ(通常はawkまたはPerlで書かれています)があります。
- 明確に定義されたフィールド構造を持たない入力パターン(例:/var/log/messages)が多いため、より一般的な正規表現ベースの技術を使用する必要があります。
4番目の質問である出力構造の変更から自分を保護する方法は、実際にできる唯一の質問です。
- 〜のように@jw013さんが言った。、posix標準の内容を確認してください。もちろん、posixは入力ソースとして使用したいすべてのコマンドを指定しません。
- スクリプトを移植可能にするには、インストールしたコマンドバージョンの機能を避けてください。たとえば、標準の Unix コマンドの多くの GNU バージョンには非標準拡張があります。これは役に立ちますが、最大の移植性が必要な場合は避けるべきです。
- コマンドパラメータのサブセットと出力形式がプラットフォーム全体で安定している傾向があるかどうかを理解してください。残念ながら、これらの違いは非公式にもどこにも文書化されていないため、時間の経過とともに複数のプラットフォームにアクセスする必要があります。
結局のところ、心配する問題から自分自身を完全に保護することはできず、コマンドが実行する必要がある作業の「明確な」説明を見つける場所はありません。多くのシェルスクリプト、特に個人用または小規模の使用用に作成されたスクリプトの場合、これはまったく問題ではありません。
答え4
事実上のIO標準(空白とnullで区切られた出力)のみがあります。
互換性については、通常、個々のフィルタのバージョン番号を確認します。あまり変わったわけではありませんが、新機能を使用してまだ古いバージョンでスクリプトを実行するには、どういうわけか「ifdef」が必要です。実際にテストケースを手動で作成する以外に、機能報告メカニズムはありません。