zsh エイリアスがあります。
gitbs() {
git branch | grep -- $1
}
次のように結果をgit checkoutに渡したいと思います。
git checkout | gitbs state
どうすればこれを行うことができますか?
答え1
シェルパイプは、あるコマンドの出力を別のコマンドの入力に渡します。ここでは役に立ちません。コマンドの出力をコマンドライン引数として別のコマンドに渡そうとします。これを行うツールは次のとおりです。コマンドの置き換え。だから基本的なアイデアは
git checkout "$(gitbs state)"
(これはパイプですが、パイプの読み取り端はシェル自体です。出力を読み取ってから、その出力を含むコマンドラインを設定します。)
ただし、出力はgitbs state
渡すのに正しい形式ではありませんgit checkout
。ブランチ名と同じ行に追加のスペースがあり、時には句読点があります。 (色の書式設定コードもありますが、出力が端末に渡された場合、またはgitが自動的にポケットベルを呼び出す場合にのみ適用され、出力がパイプである場合はありません)。情報のエラーgit checkout
。
gitbs
この問題を解決するには、元のブランチ名を出力として生成するように変更できます。以下は、出力が端末の場合は人のためのきれいな形式を維持し、それ以外の場合は1行に分岐名を印刷するバージョンです。それを使うgit for-each-ref
支店名を列挙します。これ条件式 -t 1
標準出力が端末かどうかをテストします。
gitbs () {
if [[ -t 1 ]]; then
git branch
else
git for-each-ref --format='%(refname:lstrip=2)' 'refs/heads/*'
fi | grep -- "$1"
}
この定義でgitbs
それはgit checkout "$(gitbs state)"
すべてです。
コマンド置換の周りに二重引用符があります。二重引用符()がない場合、出力はスペースから別の引数に分割されるため、複数のブランチが一致すると、結果コマンドはチェックアウトするのではなく、ファイルの現在のバージョンをgit checkout $(gitbs state)
git checkout foobar1 foobar2
ifのバージョンで上書きします。名前のファイルが存在します。foobar1
foobar2
foobar1
foobar2
gitbs
これらのトラップを回避するには、一致する単一のブランチが必要な別のバージョンを定義することをお勧めします。一致するブランチがゼロを超える場合、現在のブランチに関する追加メッセージは引き続き表示されますが、より明確なエラーメッセージが表示されますgit checkout
。この関数は一致する分岐のリストを大量に
gitbs1 () {
local branches
branches=($(git for-each-ref --format='%(refname:lstrip=2)' 'refs/heads/*' | grep "$1"))
if ((#branches == 0)); then
echo "No branch contains '$1'" >&2
return 3
fi
if ((#branches > 1)); then
echo "Multiple branches match '$1':" >&2
print -lr $branches >&2
return 3
fi
echo $branches
}
これで自信を持って書くことができますgit checkout $(gitbs1 state)
。
このオプションをオンにするとglob_complete
(つまりsetopt glob_complete
、.zshrc
)次に入力できます。
子ブランチ *foo*Tab
*foo*
一致するブランチの名前(存在する場合)に置き換えられます。一致するブランチが複数ある場合は、一般(プレフィックス)完了と同じ種類のメニューまたはループ動作が発生します。
答え2
これはエイリアスではなく関数です。
コマンド出力の単語を引数として他のコマンドに渡す場合は、コマンドの置き換えは次のようになります。
git checkout $(gitbs state)
キャプチャされた出力gitbs state
(ここでは関数、エイリアス、または外部コマンドであるかどうかは重要ではありません)を取得し、末尾の改行、区切り文字を削除し、結果の単語を$IFS
別の引数としてgit checkout
1に渡します。
分割結果の最初の単語だけを渡します。
git checkout ${$(gitbs state)[1]}
出力全体(末尾の改行を除く)を次のように渡します。一つパラメータについては、git checkout
以下を参照してください。
git checkout "$(gitbs state)"
$IFS
文字の代わりに任意の文字列に分割するには、パラメータs
拡張フラグを使用します(またはf
改行に分割)。
git checkout ${(f)"$(gitbs state)"}
(空の要素は削除されます。)
このxargs
コマンドはこの目的に使用できますが、分割はxargs
非常に特定の方法で実行され、xargs
外部コマンド(シェル組み込みまたは機能ではない)のみを実行できます。
gitbs state | xargs git checkout
xargs
多数の単語が出力される場合(単一のコマンドラインに入ることができるよりも多くの単語)、この操作は複数回実行できますgit checkout
。gitbs state
set -o noglob
1 Bourneなどの他のシェルでは、結果の単語に対するこの操作を防ぐためにワイルドカード()を無効にする必要があります。zsh
sh/ksh エミュレーションモード以外は適用されません。