BashユーザのためのFish

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

Fishは、POSIX互換ではないため、Bash等の他のシェルとは異なる動作をするものがある。

いずれのシェルも、基本的にコマンドラインの拡張、パイプ、リダイレクト、変数、グロブを備えており、様々な方法でコマンド出力を使用する。


コマンドの置換

Fishはコマンド置換を、$(command)、または、(command)と記述する。

また、Fishには、$IFSは存在せず、改行で分割する。
それ以外の方法で分割する場合は、splitコマンド、string split0コマンド、string collectコマンドのいずれかを使用する。

詳細は、Fishの基礎 - 繰り返し文#for文を参照すること。


変数

Fishは、setコマンドにより変数の設定や消去を行う。
また、declareコマンド、unsetコマンド、exportコマンド等の様々な個別の組み込みを行う。

例えば、setコマンドは、オプションで変数のスコープやエクスポートの可否を決定する。

 # 変数PAGERをグローバルに定義およびエクスポートすることにより、export PAGER=lessと同様になる
 set -gx PAGER less
 
 # alocalvariable=fooのように、$alocalvariableをローカルにのみ定義する
 set -l alocalvariable foo


変数を消去する。

 set -e PAGER


<変数名>=<値>文は、環境のオーバーライドとして利用できる。

 PAGER=cat git log


Fishは、単語の分割を行わないため、変数に値が設定されると、その値はそのまま維持される。
そのため、Bashのように変数の展開をダブルクオートで記述する必要はない。

 # Bashの場合
 # ダブルクォートを使用していないため、ワードスプリッティング(2行で表示)となる
 
 foo="bar baz"
 printf '%s\n' $foo
 
 # 出力
 bar
 baz


 # Fishの場合
 # 変数fooは1つの要素として設定されているため、1つの要素として渡される (1行で表示される)
 set foo "bar baz"
 printf '%s\n' $foo
 
 # 出力
 foo baz


変数は全て配列(リスト)であるため、変数を展開するとその全ての要素が展開される。
配列の各要素は、それ自身の引数となる。(Bashでいう${var[@]}と同様)

 set var "foo bar" banana
 printf '%s\n' $var
 
 # 出力
 foo bar
 banana


リストの特定の要素を選択することができます。

 echo $list[5..7]


setコマンドを使用して、コマンドの出力に変数を設定することも可能である。

 # 変数lineにfile.txtファイル内の全ての内容を設定して、1行に1つの要素を設定する
 set lines (cat file.txt)


リテラル値とコマンドを混在させて、変数に代入することも可能である。

 set numbers 1 2 3 (seq 5 8) 9
 printf '%s\n' $numbers
 
 # 出力
 1
 2
 3
 5
 6
 7
 8
 9


set <変数名> = <値>コマンドは間違ったシンタックスであり、変数に2つの値(=と<値>)を代入してしまう。


ワイルドカード

Fishは、構文として*グロブおよび**グロブ(および非推奨の?グロブ)のみをサポートしている。
ただし、for文、setcount、グロブが変数オーバーライド(set VAR *文等)が使用されている場合は、(Bashのnullglobオプションのように)何もない状態に展開される。

グロブは展開された変数では適用されないため、以下に示すような記述は、どのファイルにもマッチしない。

 set foo "*"
 echo $foo


引用符で囲まれていない*、または、?が含まれている場合、それをワイルドカードとして使用することができる。

  • *
    ファイル名に含まれる任意の文字数(0を含む)にマッチする。(/は含まれない)

  • **
    任意の数の文字(0を含む)に再帰的にマッチする。(サブディレクトリは降順)
    自身のセグメントである場合は、他のシェルとの互換性のために、そのセグメントもマッチする可能性がある。

  • ?
    /以外の任意の1文字にマッチする。
    ただし、?の使用は非推奨であり、qmark-noglob機能フラグで無効にできるため、?は通常の文字として扱うことができる。


ワイルドカードのマッチは、大文字小文字を区別せずにソートされる。
数字を含むマッチをソートする場合、それらは自然にソートされて、'1'、'5'、'12'という文字列は1,5,12のようにソートされる。

隠しファイル(名前がドットで始まるもの)は、ワイルドカードの文字列がその場所にドットを持たない限り、ワイルドカードを使用する際に考慮されない。

  • a*
    現在のディレクトリにある'a'で始まる全てのファイルにマッチする。

  • **
    カレントディレクトリとそのサブディレクトリにある全てのファイルとディレクトリにマッチする。

  • ~/.*
    ホームディレクトリにある全ての隠しファイルとディレクトリにマッチする。


多くのコマンドでは、ワイルドカードの展開に失敗する時、コマンドは実行されずに環境変数status0以外に設定されて、警告が表示される。
この動作は、Bashがshopt -s failglobで行うのと同様である。

例外として、setpathoverrides文での変数のオーバーライド、count文、for文がある。
これらのグロブは、Bashのshopt -s nullglobのように、引数ゼロに展開される。

 # .txtファイルをリストアップして、存在しない場合は警告を表示する
 ls *.txt


 # .txtファイルが存在する場合は、その一覧を表示する
 set foos *.txt
 if count $foos >/dev/null
    ls $foos
 end


Bashとは異なり、Fishは(デフォルトでは)マッチしない場合、リテラルなグロブ文字を渡さないため、
findコマンドやsudo zypper installのようにマッチング自体を行うコマンドでは、引用符を追加する必要がある。

 sudo zypper install "ncurses-*"
 find . -iname "*.txt"



引用符

Fishには、2つの引用符""''がある。
変数はダブルクォートで展開されて、引用符が無い場合はシングルクォートで展開される。

また、$は存在しないが、変換されるようなシーケンスはクォートされていない時に変換される。

 echo a\nb
 
 # 出力
 a
 b


パラメータ展開や文字エスケープの機能を無視する場合、'または"を使用する。
'の間では、Fishは展開を行わない。
"の間では、Fishは変数の展開のみを行う。

他の種類の展開(波括弧の展開やパラメータの展開を含む)は行われず、エスケープシーケンス(例. \n)は無視される。
引用符の中では、引数の区切りに空白を使用しないため、引用符で囲まれた引数に空白を含めることができる。

'をエスケープする場合は\'"をエスケープする場合は\"、ドル文字をエスケープする場合は\$、バックスラッシュと改行を削除する場合は\、バックスラッシュ記号をエスケープする場合は\\である。

'"内では特別な意味を持たないが、その逆も同様である。

 # "cumbersome filename.txt"という名前のファイルを削除する
 rm "cumbersome filename.txt"
 
 # "cumbersome"ファイルと"filename.txt"ファイルの2つのファイルを削除する
 rm cumbersome filename.txt
 
 # foo.txtファイルの内容から、enabled)で終わる行を検索する
 # (grepコマンドにおいて、$記号は行末にマッチする)
 grep 'enabled)$' foo.txt



文字列の操作

Fishの文字列の操作は、stringコマンド(組み込み関数)により行われる。

"bar "を"baz "に置換する。

 string replace bar baz "bar luhrmann"
 
 # 出力
 baz luhrmann


文字列を分割する。

 string split "," "foo,bar"
 
 # 出力
 foo
 bar


grepコマンドの代替として、正規表現にマッチする。

 echo bababa | string match -r 'aba$'
 
 # 出力
 aba


文字列を任意の文字で、指定された幅になるように埋める。

 string pad -c x -w 20 "foo"
 
 # 出力
 xxxxxxxxxxxxxxxxxfoo


文字列を小文字または大文字にする。

 # 小文字に変換する
 string lower Foo
 
 # 出力
 foo
 
 # 大文字に変換する
 string upper Foo
 
 # 出力
 FOO


その他、文字列のリピート、文字列のトリム、文字列のエスケープ、文字列の長さや幅の表示(端末セル単位)を行うこともできる。


特殊な変数

下表に、FishとBashの特殊な変数の比較を示す。

Bash Fish
$*
$@
$argv
$1
$2
$argv[1]
$argv[2]
$? $status
$$ $fish_pid
$# Fishには存在しないため、
count $argvコマンドを使用する。
$! $last_pid
$0 Fishには存在しないため、
status filenameコマンドを使用する。
$- Fishには存在しないため、
status is-interactiveまたはstatus is-loginを使用する。



ヒアドキュメント

Fishは、<<EOF文は存在しないため、printf文、または、""と改行を使用して、ヒアドキュメントを行う。

 printf %s\n "some string" "some more string"
 
 # または
 
 echo "some string
 some more string"
 
 # または、引用符を別の行にする場合
 
 echo "\
 some string
 some more string\
 "


ヒアドキュメントが行うことを、以下に示す。

  • 文字列を特殊なルールで終端まで読み取り、解釈する。
  • 結果の文字列を一時ファイルに書き出す。
  • そのファイルを標準入力として、ヒアドキュメントが添付されているコマンドを起動する。


ヒアドキュメントと同様に、コマンドはstdinから読み込むように準備しなければならない。
これには特別なオプションが必要なこともあり、多くの場合、ファイル名を-で与えることにより有効になる。

 echo "xterm
 rxvt-unicode" | sudo zypper remove -
 
 # 以下に示すコマンドと同様である
 # -は、zypperが標準入力から引数を読み込むようにしている
 sudo zypper remove xterm rxvt-unicode


ヒアドキュメントは、多くの特殊なルールを導入するマイナーな構文上の味付けに過ぎないため、Fishではパイプを使用することにより、簡潔に記述・構成することができる。


算術演算

Fishでは、算術演算はmathコマンドにより処理される。

 math $i + 1


他のシェルの算術演算と異なり、Fishでは浮動小数点数を扱うことができる。

 math 5 / 2
 
 # 出力
 2.5


三角測量のような機能も存在する。

 math cos 2 x pi
 
 # 出力
 1


mathコマンドの引数は、別々に渡す、または、引用符で囲んで渡すことができる。
Fishは、コマンド実行に()を使用するため、式の中で使用する場合は、引用符で囲む必要がある。

 math '(5 + 2) * 4'


*とxは両方ともFishにおける乗算記号であるが、*を使用する場合は、引用符で囲む必要がある。(グロブに見えるため)


プロンプト

Fishは、$PS1$PS2等の特殊変数は存在しない。
fish_prompt関数の出力、または、vi-modeが有効な場合はfish_mode_prompt関数、右プロンプトの場合はfish_right_prompt関数を加えたものが使用できる。

  • テキストに色を付けるため、set_colorを提供している。
    これは、16色の名前付きカラーやRGBカラー(例. set_color 5555FF)を使用することができる。
  • プロンプトに何かを追加するためのヘルパー関数が存在する。
    例1. バージョン管理システム(git、mercurial、svn)の表示を追加するfish_vcs_prompt関数
    例2. 現在の場所(ユーザのホームディレクトリは~になり、パスの構成要素が全て短縮される)を表示するprompt_pwd関数
    例3. ホスト名を短縮して表示するprompt_hostname関数
 function fish_prompt
    set -l prompt_symbol '$'
    fish_is_root_user; and set prompt_symbol '#'
 
    echo -s (prompt_hostname) \
    (set_color blue) (prompt_pwd) \
    (set_color yellow) $prompt_symbol (set_color normal)
 end


デフォルトのプロンプトを確認する場合は、fish_promptコマンドを実行することにより、表示することができる。

Fishは、継続行のための$PS2は存在しない。
コマンドラインがまだ完了していないことを示すため、行をインデントしたままにしている。


ブロック

FishとBashのブロックの構成を比較する。

 # Bash
 
 {
   echo Hello
 }


 # Fish
 
 begin
    echo Hello
 end



ビルトインおよびその他のコマンド

Fishは、構文よりもビルトインコマンドや外部コマンドに重点を置いている。
使用頻度の高いビルトインコマンドを、以下に示す。

  • stringコマンド
    文字列変換(Bashにおける${i%foo}等)を行うことができる。
    また、grepコマンドやsedコマンド等の代わりに使用することができる。

  • mathコマンド
    Bashにおける$((i + 1))の演算を置き換えることができる。
    また、浮動小数点や簡単な関数(三角関数等)も扱うことができる。

  • argparseコマンド
    引数をパースすることができる。
    これは、Bashにおけるgetoptコマンド、または、Zshにおけるzparseoptsコマンドと同様のコマンドである。

  • countコマンド
    要素数等を数えることができるため、Bashにおける$#を置き換えることができる。
    またh、wcコマンドの代わりに使用することができる。

  • statusコマンド
    Fishの状態に関する情報(例. 対話型かどうか、現在のリネン番号等)を提供する。
    Bashにおける$-$BASH_LINENO等の特殊変数を置き換えることができる。

  • seq(1)コマンド
    Bashにおける{1..10}の範囲拡張の代わりとして使用することができる。
    また、seqコマンドは別のコマンドに置き換えることができる。