アプリケーションの開発中に、疑問に思い始めました-コマンドライン引数をどのように設計すればよいですか?
多くのプログラムがこの-argument value
または/argument value
のような式を使用しています。私の頭に浮かんだ解決策はargument:value
でした。空白がないと、値や引数をめちゃくちゃにする方法がないので、それは良いと思いました。また、左側の:
文字から最初に文字列を2つに分割するのも簡単です。
私の質問は:
-argument value
の式はargument:value
よりも優れていますか(読みやすく、書きやすく、バグがなく、専門の開発者にとって理解しやすい)。私はそれを提供するいくつかの詳細について尋ねた。しかし、私はそれらが答えに影響を与えるべきではないと思います。問題は、一般的に良い習慣についてです。すべての種類のアプリケーションですべて同じだと思います。
公共の場(タッチトーテム、テーブル)で使用されるアプリケーションを開発中です。アプリケーションはQt Quick 5(C++、QML、JS)を使用して記述されています。デバイスにはWindows 8.1/10がインストールされます。デバイスを管理するためのフロントエンドインターフェイスを提供します。ただし、一部の上級管理者は、自分でアプリケーションを構成したい場合があります。それはビジネスの側からはそれほど重要ではありませんが、私が同意するように Kilian Foth は、自分のアプリケーションがユーザーの負担になることを望んでいないと述べました。インターネットで私が欲しいものを見つけられなかったので、ここで尋ねました。
Stack Exchangeの上級ユーザー向け:この質問は一般的なものにしたかった。たぶんそれはコミュニティーwikiに適格です(既存の質問を回答で変換できるかどうかはわかりません)。この質問をオペレーティングシステムやプログラミング言語に依存しないようにしたいので、ここに表示される回答は他の開発者にとって貴重な教訓になる可能性があります。
POSIXシステム(Linux、MacOSXなど)では、少なくともシェルターミナルで起動された可能性のあるプログラム(たとえば、ほとんどのプログラム)では、 GNUコーディング規約 (一般的な引数名もリストされます)の使用をお勧めします。 POSIXユーティリティガイドライン を調べてください。プロプライエタリソフトウェアについても同様です。
常に_--version
_および_--help
_を処理します(_/bin/true
_でも受け入れられます!!)。 _--help
_を理解していないソフトウェアの作者をののしりました。嫌いです(_prog --help
_は最初のコマンドなので、新しいプログラムに取り組んでいます)。しばしば_--help
_は_-h
_と省略できます
_--help
_メッセージにすべてのオプションをリストしてもらいます(オプションが多すぎる場合を除きます...その場合、最も一般的なオプションをリストし、explicitlyいくつかのman
ページを参照しますまたはいくつかのURL)およびオプションのデフォルト値、そしておそらく重要な(そしてプログラム固有の)環境変数。オプション引数エラー時にこれらのオプションリストを表示します。
_-a
_短い引数(1文字)を受け入れ、同等の_--long-argument
_をいくつか持つため、_-a2
_ _--long-argument=2
_、_--long-argument 2
_;もちろん、(ほとんど使用されないオプションの場合)_--only-long-argument
_の名前を付けることができます。余分なオプションのないモーダル引数の場合、_-cf
_は通常_-c -f
_などとして処理されるため、_-argument:value
_の提案はおかしいので、お勧めしません。
gLIBCを使用 getopt_long 以上(例 argp_parse 、OCamlでは Arg
module 、...)
標準入力または出力に_-
_をよく使用します(それができない場合は、_/dev/stdin
_および_/dev/stdout
_を、それらを持たないいくつかのオペレーティングシステムでも処理します)。
ほとんどのオプションの規則を再利用することにより、同様のプログラムの動作を模倣します。特に、ドライランの場合は_-n
_(àmake
)、ヘルプの場合は_-h
_、詳細度の場合は_-v
_など...
オプションとファイルまたは他の引数の間の区切り文字として_--
_を使用します
プログラムがisatty
を使用してstdinよりもテストする場合(およびその場合は「対話式」に動作します)、プログラムに次のように、非対話モードを強制するオプションを提供しますGUIインターフェイス(およびX11デスクトップでgetenv("DISPLAY")
をテスト)。ただし、バッチまたはコマンドラインで使用することもできます。
一部のプログラム(例:gcc
)は間接引数リストを受け入れるため、_@somefile.txt
_は_somefile.txt
_からプログラム引数を読み取ることを意味します。これは、プログラムが非常に多くの引数(カーネルの_ARG_MAX
_よりも多い)を受け入れる可能性がある場合に役立ちます。
ところで、プログラムや通常のシェル(bash
やzsh
など)にオートコンプリート機能を追加することもできます
一部の古いUnixコマンド(例:dd
、またはsed
)には、歴史的な互換性のために奇妙なコマンド引数があります。私は彼らの悪い習慣を守らないことをお勧めします(あなたがそれらのより良い変種を作っているのでない限り)。
ソフトウェアが関連する一連のコマンドラインプログラムである場合、_git help
_と_git --help
_を受け入れて git (開発ツールとして使用する)からインスピレーションを得て、多くのgit
subcommand
およびgit
subcommand
_--help
_
まれなケースでは、_argv[0]
_を(プログラムでシンボリックリンクを使用して)使用することもできます。 bash
として呼び出されたrbash
の動作は異なります( 制限付き シェル)。しかし、私は通常、それを行うことをお勧めしません。 Shebang を使用してスクリプトインタープリターとしてプログラムを使用できる場合、つまり execve(2) によって解釈される最初の行の_#!
_が意味をなす場合があります。そのようなトリックを行う場合は、必ず_--help
_メッセージに含めて、それらを文書化してください。
POSIXではShellは globbing 引数(beforeプログラムの実行!)であることを忘れないでください。したがって、(_*
_またはシェルエスケープする必要があるオプションの_$
_または_~
_)。
場合によっては、ソフトウェアに GNU guile または Lua のようなインタープリターを埋め込むことができます(独自の Turing-complete スクリプト言語を発明することは避けてください)プログラミング言語の専門家ではありません)。これはソフトウェアの設計に深い影響を与えます(そのため、早い段階で考えるべきです)。そうすれば、そのインタプリタにスクリプトや式を簡単に渡すことができるはずです。その興味深いアプローチを取る場合は、ソフトウェアとその解釈済みプリミティブを注意深く設計してください。奇妙なユーザーがあなたの事物のために大きなスクリプトをコーディングするかもしれません。
他のケースでは、上級ユーザーが プラグイン をソフトウェアにロードできるようにすることもできます( 動的ロード テクニックàla dlopen
)を使用 &dlsym
)。繰り返しますが、これは非常に重要な設計上の決定です(したがって、プラグインインターフェイスを慎重に定義して文書化してください)。これらのプラグインにプログラムオプションを渡すための規則を定義する必要があります。
ソフトウェアが複雑な場合は、いくつかの 構成ファイル (プログラム引数の追加または置換)を受け入れ、おそらくすべてのコードを実行せずにこれらの構成ファイルをテストする(または単に解析する)方法をいくつか用意します。 。たとえば、メール転送エージェント(EximやPostfixなど)は非常に複雑であり、「ハーフドライ」で実行できると便利です(たとえば、実際にメールを送信せずに特定のメールアドレスをどのように処理しているかを監視する)。
_/option
_はWindowsまたはVMSのものであることに注意してください。 POSIXシステムでは正気ではありません(ファイル階層が_/
_をディレクトリセパレータとして使用しているため、シェルがグロビングを行うため)。私の答えはほとんどがLinux(およびPOSIX)に関するものです。
追伸可能であれば、プログラムを フリーソフトウェア にすると、一部のユーザーや開発者から改善が得られます(多くの場合、新しいプログラムオプションの追加は、既存のフリーソフトウェアに追加する最も簡単な方法の1つです)。また、質問はたくさん対象読者によって異なります:ティーンエイジャー向けのゲームやおばあちゃん向けのブラウザはおそらく必要ありませんコンパイラ、データセンターのシステム管理者向けのネットワークインスペクタ、またはマイクロプロセッサアーキテクトやブリッジデザイナ向けのCADソフトウェア)と同じ種類と量のオプション。おばあちゃんよりも多くの調整可能なオプションがあり、おそらくX11なしでアプリケーションを実行できるようにしたい場合があります(おそらくcrontab
ジョブで)。
データ形式の規則が一般的であるという事実isその利点。
=または:または ''を区切り文字として使用しても、わずかな労力でコンピューターによって相互に変換できる些細な違いであることが簡単にわかります。 bigの取り組みとは、人間が覚えていることです。「さて、このあまり使用されないプログラムが:
または=
?うーん...」
言い換えれば、神の愛のために、説得力のある理由なしに非常に定着した慣習から逸脱しないでください。人々はあなたのプログラムを「私の大学のエッセイを救ったプログラム」ではなく、「奇妙で煩わしいcmdline構文を持つプログラム」として覚えています。
簡単に言えば
ローマにいるときは、ローマ人がするようにしてください。
-p value
または--parameter value
の規則を使用してください。 Linuxには、そのようなパラメーターとフラグを簡単に解析するためのツールがあります。私は通常次のようなことをします:
while [[ $# > 0 ]]
do
key="$1"
case $key in
--dummy)
#this is a flag do something here
;;
--audit_sessiones)
#this is a flag do something here
;;
--destination_path)
# this is a key-value parameter
# the value is always in $2 ,
# you must shift to skip over for the next iteration
path=$2
shift
;;
*)
# unknown option
;;
esac
shift
done
CLIアプリがWindows用の場合は、/flag
および/flag:value
の規則を使用してください。
ただし、Oracleのような一部のアプリはどちらも使用しません。 OracleユーティリティはPARAMETER=VALUE
を使用します。
私がやりたいことの1つは、コマンドラインでパラメーターを受け入れる以外に、parfileを使用するオプションを提供するです。これは、長いパラメーターチェーンを回避するためのキーと値のペアファイルです。そのためには、追加の--parfile mifile.par
パラメータを提供する必要があります。 --parfile
が使用されている場合、他のすべてのパラメーターは破棄され、parfile内にあるものが優先されます。
追加の提案は一部のカスタム環境変数の使用を許可することです。たとえば、環境変数MYAPP_WRKSPACE=/tmp
を設定すると、常に--wrkspace /tmp
を設定する必要がなくなります。
TAB
を押すと、シェルがそれを完了します。まだ思いつかなかったことの1つ:
ソフトウェアを設計してみてくださいコマンドライン引数から以上。意味:
機能を設計する前に、ユーザーインターフェイスを設計します。
これにより、エッジのケースと一般的なケースを早い段階でドリルダウンできます。もちろん、外側と内側を抽象化しますが、すべてのコードを記述してCLIを非難するよりもはるかに良い結果が得られます。
さらに、docopt( http://docopt.org/ )を確認してください。
docoptは、特にpythonが非常に制限されており、argparseのようなユーザーに悪影響を与える引数パーサーが「OK」と見なされている場合)において、多くの言語でこれに非常に役立ちます。パーサーとサブパーサーの代わりに条件付きディクテーションでは、構文ヘルプを定義するだけで、あとは残ります。
いくつかの貴重なコメントはすでに提供されていますが(@ Florian、Basile)、追加させてください... OPは言う、
デバイスを管理するためのフロントエンドインターフェイスを提供します。ただし、一部の上級管理者は、自分でアプリケーションを構成したい場合があります。
しかしまた、備考:
この質問がプラットフォームや言語固有になることを望んでいません
ターゲットオーディエンスを考慮する必要があります-上級管理者。彼らは通常どのプラットフォームで動作しますか-Win/Unix/Mac?また、アプリはどのプラットフォームで動作しますか?そのプラットフォームですでに確立されているCLI規則に従ってください。 「高度な」管理者は、GUIベースのツールを必要としていますか?
インターフェースを内部的に、および他の管理ツールと整合させる必要があります。やめたくない、それだと思うcmd -p <arg>
またはcmd -p:<arg>
またはcmd /p <arg>
。スペースはありますか? cmd -p <val1> <val2>
またはcmd -p <val1> -p <val2>
複数のターゲットの場合?特定の注文ですか?過負荷?しますcmd -p2 <arg> -p1 <arg>
仕事もしますか?しますls -l -r -t dir1 dir2
== ls -trl dir1 dir2
?
私のUnix管理ツールについては、 Heiner's Shelldorado によって提供されるガイダンスと、言及されている他のリファレンスを常に念頭に置いてきました。
CLIの設計と同様に重要なことは、アプリケーションがGUIと同じようにコマンドライン引数で機能するように設計されていることを確認することです。つまり、GUIにビジネスロジックがないか、GUIとCLIの両方から呼び出される共通コマンドを使用します。
ほとんどのUNIXベースの管理ツールは、実際には最初にコマンドラインツールとして設計されており、提供されているGUIはコマンドラインのオプションの「入力」を容易にします。このアプローチにより、自動化、応答ファイルの使用などが可能になり、ハンズオフ管理が可能になります(私にとっては手間がかかりません)
このアプローチで使用されるクラシックツールセットは Tcl/Tk です。ツールの切り替えは提案していません。最初に、GUIベースの管理アプリをコマンドラインツールとしてアプリに書き込むことから、設計アプローチを検討してください。次に、便宜上、GUIを上に重ねます。複数の構成を行い、一般的に同じオプションを何度も再入力する必要がある場合、GUIが面倒(そしてエラーが発生しやすい)であることに気づくでしょう。自動化されたアプローチを探します。
いずれにしても、管理者は正しいボックスに正しい値を入力する必要がある可能性があるため、GUIを使用して、どれほどの労力を軽減できますか?