モチベーション
作業ログを書いている際にコマンドをコピーしたい場面がある。今まではマウスで選択して右クリックでコピーをしていたが自動化チャンスだと思ったのでやる。
コマンド全体
> echo `history -1` | cut -f 2- -d " " | pbcopy
アプローチ
zshのコマンドの履歴は ~/.zsh_history
に保存されているので覗いてみる。
> cat ~/.zsh_history | head -n 5 : 1661521409:0;ls : 1661521409:0;gs : 1661521409:0;cd contrail : 1661521409:0;cd generated : 1661521409:0;cd ..
適当に文字列いじれば取れるけど他に無いかなと探していると、oh-my-zshに history
コマンド*2なるものがあることを見つけた。
> history | head -n 5 1 ls 2 gs 3 cd contrail 4 cd generated 5 cd ..
見た感じ内部で ~/.zsh_history
を参照していて中身は同じっぽい。こっちをいじった方がシンプルそう。
…とはいえ簡単にはいかなそう。
> history | head -n 2 1 ls 2 gs > history | tail -n 2 1930 history | head -n 2 1931 history | head -n 10
行の先頭の番号が持ちうる最大桁数分をスペースで埋めていた。素直に cut -b {バイト数}
とかができない。 ~/.zsh_history
でいじったほうが良さそう? 見切りをつけるためにもう少し粘る。history
コマンドの実行結果を眺める。
> history | tail -n 10 1932 history | tail -n 2 1933 history | tail -n 1 | cut -d " " 1934 history | tail -n 1 | cut -f 1 -d " " 1935 history | tail -n 1 | cut -f 2 -d " " 1936 history | head -n 1 | cut -f 2 -d " " 1937 history | head -n 1 | cut -f 3 -d " " 1938 history | head -n 1 | cut -f 5 -d " " 1939 history | head -n 1 | cut -f 4 -d " " 1940 history | head -n 1 1941 history | head -n 10
最大桁数が表示される最後の方ならcut -d {デリミタ}
が使えそう。
> history | tail -n 5 | cut -f 2 -d " " 1940 1941 1942 1943 1944
使えた。ここの桁数を取ってみる。
> history | tail -n 1 | cut -f 2 -d " " 1965 > history | tail -n 1 | cut -f 2 -d " " | wc -c 5
4がほしいところだが5になってしまう、何か混じってる?桁数まで考えるとコマンド全体が長くなってしまう。なるべくシンプルにいきたい。もう少しひねり出す。
少し道を外すが、history
コマンドのソースコードを眺めているとheadやtailに渡さなくても数字を渡せば欲しい行数を指定できることに気がついた。
> history -1 2003 history 1
…いやよく考えたら cut -f {A} -d {デリミタ}
でAに渡すものを2以降にできれば解決できないか?ということで、オプションfに 2-
を渡すことで解決した。
# 適当なコマンド > echo "hoge" | sed -e "s/o/e/" | sed -e "s/e/i/g" higi # 一つ前に実行したコマンドが表示される > echo `history -1` | cut -f 2- -d " " echo "hoge" | sed -e "s/o/e/" | sed -e "s/e/i/g" # 一つ前に実行したコマンドをクリップボードにコピー > echo `history -1` | cut -f 2- -d " " | pbcopy
history -1
で渡すと改行コードが入ってしまうのが面倒だったりするのでechoに渡している。