fish(フレンドリーな対話型シェル、小文字で表記)は、対話性と使いやすさを重視したUnixライクなシェルです。fishは、高度な設定変更ではなく、デフォルトで豊富な機能を備えるように設計されており[ 8 ] 、設計上POSIXシェル標準には準拠していません[ 9 ] 。
fish は、コマンド履歴と現在のディレクトリに基づいて、ユーザーが入力するにつれて候補を段階的に表示します。これはBashのCtrl+R履歴検索と似た機能ですが、常に有効になっているため、コマンドを入力している間、ユーザーに継続的なフィードバックを提供します。fish には、ファイルパスの展開(ワイルドカードと中括弧展開を使用)、環境変数、コマンド固有の補完をサポートする、機能豊富なタブ補完も含まれています。説明付きのオプションを含むコマンド固有の補完は、ある程度コマンドのman ページから生成できますが、カスタム補完はソフトウェアに含めたり、シェルのユーザーが作成したりすることもできます。[ 10 ]
fish の開発者は、構文ではなくコマンドとして新機能を追加することを好みました。これにより、組み込み機能によってオプションやヘルプ テキスト付きのコマンドを検索できるため、機能が発見しやすくなりました。関数には、人間が読める説明を含めることもできます。特別なhelpコマンドを使用すると、ユーザーのWeb ブラウザで fish のすべてのドキュメントにアクセスできます。[ 11 ]
構文はPOSIX互換シェル(Bashなど)に似ているが、多くの点で異なっている[ 12 ]
# 変数の代入# # 変数 'foo' に値 'bar' を設定します。# fish は、本質的に空白文字に敏感な = 演算子を使用しません。# 'set' コマンドは、配列、スコープなどを扱うように拡張されています。> set foo bar > echo $foo バー # コマンド置換# # コマンド 'pwd' の出力を変数 'wd' に代入します。# fish ではバッククォート (``) は使用されません。バッククォートはネストできず、シングルクォート (' ') と混同される可能性があります。> set wd ( pwd ) > set wd $( pwd ) # バージョン 3.4 以降> echo $wd ~ # 配列変数。「A」は5つの値を持つ配列になります。> set A 3 5 7 9 12 # 配列スライス。「B」は「A」の最初の2つの要素になります。> set B $A [ 1 2 ] > echo $B 3 5 # 他の配列やコマンドの置換出力でインデックス付けすることもできます。> echo $A [( seq 3 )] 3 5 7 # 「A」の3番目と5番目の要素を削除します。> set --erase A [ $B ] > echo $A 3 5 9 # forループ、JPEGをPNGに変換> for i in *.jpg convert $i ( basename $i .jpg ) .png end# fish は複数行の履歴と編集をサポートしています。# セミコロンは改行のように機能します: > for i in *.jpg ; convert $i ( basename $i .jpg ) .png ; end# whileループで/etc/passwdの各行を読み込み、ファイルから5番目のコロン区切りのフィールドを出力します。これはユーザーの説明である必要があります。> while read line set arr ( echo $line | tr : \n ) echo $arr [ 5 ] end < /etc/passwd # 文字列置換(すべての i を I に置換)> string replace -a "i" "I" "Wikipedia" ウィキペディア パイプライン、関数、ループなどの言語構造は、他のシェル言語ではいわゆるサブシェルを使用して実装されています。サブシェルは、タスクを実行するためにいくつかのコマンドを実行し、その後親シェルに戻る子プログラムです。この実装の詳細には通常、サブシェルで行われた変数代入などの状態変更がメインシェルに反映されないという副作用があります。fish は言語機能のためにサブシェルを作成しません。すべての組み込みコマンドは親シェル内で実行されます。
# これは他の多くのシェルでは動作しません。なぜなら、組み込みコマンド「read」は# 独自のサブシェルで実行されるからです。 Bash では、パイプの右側に副作用があってはなりません。 ksh では、以下のコマンドは動作しますが、# 左側に副作用があってはなりません。 fish と zsh では、# 両側に副作用があっても構いません。> cat *.txt | read line この Bash の例は見た目通りには動作しません。ループ本体がサブシェルであるため、への更新は$found永続的ではありません。
found = '' cat /etc/fstab | while read dev mnt rest ; do if test " $mnt " = "/" ; then found = " $dev " fi done回避策:
found = '' while read dev mnt rest ; do if test " $mnt " = "/" ; then found = " $dev " fi done < /etc/fstab 魚の例:
set found '' cat /etc/fstab | while read dev mnt rest if test " $mnt " = "/" set found $dev end endfishにはユニバーサル変数と呼ばれる機能があり、ユーザーは実行中のすべてのfishシェルで変数に永続的に値を割り当てることができます。変数の値はログアウトや再起動後も保持され、更新は実行中のすべてのシェルに即座に反映されます。
# これにより、emacs がデフォルトのテキストエディタになります。'--universal' (または '-U') は、fish にこれをユニバーサル変数にするように指示します。> set --universal EDITOR emacs # このコマンドを実行すると、すべての実行中の fish インスタンスで、fish プロンプトの現在の作業ディレクトリが青色になります。> set --universal fish_color_cwd blue 構文には、変数スコープ、配列、関数など、いくつかの機能が欠落しているか、実装が不十分です。そのため、fish はいくつかの重要な箇所で Posix 構文から逸脱しています。
このページでは、Bash プログラマーがよく犯すエラーを紹介します。(...) 常に引用符を使用し、いかなる理由があっても単語分割を使用しないようにすれば、これらの落とし穴の多くを回避できます。単語分割は、Bourne シェルから受け継がれた壊れたレガシー機能であり、展開を引用符で囲まない場合はデフォルトで有効になっています。落とし穴の大部分は、引用符で囲まれていない展開、およびそれに伴う単語分割とグロビングに何らかの形で関連しています。