割りと便利だけど微妙に忘れがちなbashのコマンド(制御構造)チートシート&カーソル移動も

http://qiita.com/jpshadowapps/items/d6f9b55026637519347f

自分用にメモしておく

コマンド実行

CMD1; CMD2, CMD1 && CMD2

  • ;CMD1の結果に関わらずCMD2も実行される
  • &&CMD1の結果が正常な場合のみCMD2が実行される

CMD1 || CMD2 – 失敗時に後続コマンドを実行する

  • CMD || printf "%b" "MSG"でエラーメッセージを表示する
    • エラーメッセージ表示後exit 1したい場合 = CMD || { printf "%b" "FAILED.\n" ; exit 1 }
      • CMD || printf "%b" "FAILED.\n" ; exit 1と波括弧無しで書くと期待通り動作しない(CMDが成功時もexit 1してしまう)

CMD & – バックグラウンド実行

  • CMD &[1] 4592のようにジョブ番号とプロセスIDが表示される
    • killしたければkill %ジョブ番号kill プロセスID する
    • フォワグラウンド実行に戻したければ
  • $!で、直前にバックグラウンド実行したジョブのプロセスIDを取得可能
  • さらに wait ${PID}で待つと、バックグラウンドジョブが終了するまで待つことが出来る
    # バックグラウンドで実行したhubotの終了を待つ例
    ./bin/hubot -a ${HUBOT_ADAPTER} --name ${HUBOT_IRC_NICK} 2>&1 &
    HUBOT_PID=$!  # PIDを取得

    wait ${HUBOT_PID}  # ここで終了まで待つ
    RET=$?  # wait直後の $? で、バックグラウンドジョブの終了コードを取得できる
    echo "Hubot is end. PID: ${HUBOT_PID}"

$(CMD) – サブシェルでコマンド実行、実行結果は$()に置換される

  • 結果の改行はスペースに置換される
    • $IFS変数によって決まる(これのデフォルトがスペース)

nohup CMD & – 実行中のバックグラウンドジョブの継続

  • シェルを終了してもコマンドを継続したい場合につける
    • 付けずにシェルを終了すると(シェルの子プロセスである)バックグラウンドジョブには SIGHUP が送られ終了する

$? – コマンドの戻り値

  • 直前のコマンドの戻り値判定は2重括弧を使ってif (( $? ))と書ける

type, which, locate, aproposコマンドやマニュアルを探す

file, stat – ファイルの情報を表示

ドキュメンテーション

: DOCUMENT – 組み込みドキュメント

  • : <<'EOD' ... EOD

ハイフンのtips

CMD - ... ハイフンで標準入(出)力を受け取る/出力する

  • 【linux】コマンドの引数を標準入力から渡す at softelメモ
    • 「なんだよ、ファイルしか受け付けないのかよ」と思われる場合でも、ハイフンを指定すると、標準入出力への入出力が可能
    • dockerの公式インストールチュートリアルにあるwget -qO- https://get.docker.com/ | shとかもこのパターン
      • -O <ファイル名>のところを-とすることで標準出力に出して、それをそのままパイプで後続コマンドに繋げている

CMD -- ... ハイフン2つ = それ以降をコマンドラインオプションとは解釈しなくなる

  • 例えばハイフン付き文字列そのものをgrepしたいときは grep -- "-hoge" * のようにする
  • これはコマンドオプションの構文解析に使われているgetopt()の機能で、getopt()はコマンドオプションに–を見つけるとオプションの解析を終了する
  • 最近良く見るcurl http://hoge.com/huga.sh | sh形式のcurl→shインストールで、スクリプトオプションを指定したい時にも使える
    • curl -sSf https://static.rust-lang.org/rustup.sh | sh -s -- -y – rustup.sh に -y オプションを渡して実行
      • -s で標準入力からの受け取りを指定
      • -- で それ以降をただの入力文字列と解釈させる
      • -y をオプションとして入力させる

変数

シェルで「変数がセットされていない」とはどういうケースか?

  • ""空文字
  • 明示的にunset VARされた変数

$*$@の空白を含んだ引数の取り扱いの違い

  • ./hoge.sh *.txtと実行した場合
    • for FN in "$*""aaa.txt bbb ccc.txt ddd.txt"を受け取るのに対し、
    • for FN in "$@""aaa.txt" "bbb ccc.txt" "ddd.txt"を受け取る

${:-} – 変数未指定時にデフォルト値を使う

  • FILEDIR=${1:-"/tmp"} – 第1引数が “未指定” なら “/tmp”をデフォルト値として利用する
  • デフォルト値を取得・利用はするが、アサインはしない。${VAR:-"hoge"}VAR に”hoge” をセットするわけではない

${:+} – 変数指定時にデフォルト値を使う

  • FILEDIR=${VAR:+"/tmp"}VARが設定されていたら “/tmp”を(代わりに)利用する

${VAR:=} – 変数未指定時にデフォルト値を設定

  • cd ${HOME:=/tmp}${HOME} が “未指定” なら、代わりにデフォルト値をセット
    • “未指定” とはどういうケースか? = ""空文字 もしくは unsetされている ケース
  • デフォルト値を取得・利用し、変数へのアサインも行う。${VAR:="hoge"}VAR に”hoge” をセットする

${VAR=} – 変数未指定時にデフォルト値を設定, :無し

  • とにかく ${VAR:=} と混同しやすいが、こちらの “未指定” は unsetされている ケースのみが対象で、空文字は対象外

${VAR:?"MSG"} – 変数がセットされていない場合、メッセージを出力してexitする

USAGE="usage: myscript scratchdir sourcefile conversion"
FILEDIR=${1:?"Error. You must supply a scratch directory."}
FILESRC=${2:?"Error. You must supply a source file."}
CVTTYPE=${3:?"Error. ${USAGE}"}

$ ./myscript /tmp /dev/null
./myscript: line 5: 3: Error. usage: myscript scracthdir sourcefile conversion
# エラー時にコマンドを動かしたければこう書ける
CVTTYPE=${3:?"Error. $USAGE. $(rm $SCRATCHFILE)"}
# ./myscript: line 5: 3: Error. usage: myscript scracthdir sourcefile conversion


# でもこっちの方がコードの可読性は高いね。商用コードならこうすべきだね
# ただしエラーメッセージにファイル名・行番号は出力されないけどね
# ${3:?} はデバッグ時には便利だけどね

if [ -z "$3" ]
then
   echo "Error. $USAGE"
   rm $SCRATCHFILE
fi

変換

name:number:number - 部分文字列取得
#name - 文字列の長さ
name#pattern - 文字列前方のpatternを削除(最短マッチ)
name##pattern - 文字列前方のpatternを削除(最長マッチ)
name%pattern - 文字列後方のpatternを削除(最短マッチ)
name%%pattern - 文字列後方のpatternを削除(最長マッチ)
name/pattern/string - 置換(一箇所)
name//pattern/string - 置換(全体)

VAR=(VAL1 VAL2 VALn) – 配列

VAR[0] – 配列の最初の要素

VAR[@] – 配列の全要素

VAR[#] – 配列の要素数

配列

  • (VAR1 VAR2 VAR3)()(カッコ) で括って区切りを入れれば配列に変換される
  • コマンドの実行結果を配列化したい場合も同様
HOGE=$(ls -ld $1)

declare -a HUGA
HUGA=(${HOGE})  # 変数をカッコで括る
  • read -a で入力結果を配列化

setコマンド

set -e

  • スクリプト内のコマンドが失敗したらそこでスクリプトを終了する
  • set +e すれば↑を解除し、失敗しても終了しなくなる

set -o 何かOPTION

  • set -o noclobber – ファイルへの上書きリダイレクトを禁止する
    • CMD >| file>|を使うと強制的に上書きリダイレクト可能

条件分岐 if,

if [ 条件 ]

if (( 算術比較式 ))

  • 例えばif [ $VAR -eq 0 ]if (( $VAR == 0 ))と比較式記号で書ける
  • 引数の個数チェックはこう書ける
if [ $# -lt 3 ]
then
   :
fi

if (( $# < 3 ))
then
   :
fi

[ 条件 ][[ 条件 ]]

  • [ はtestコマンド、[[はbash組み込みコマンド
    • which [すると組み込みコマンドである事が分かる
  • 挙動の違いは、条件式で未定義変数を使った場合
    • [ $UNSET_VAR = "HOGE"] するとエラーを吐くが、[[ $UNSET_VAR = "HOGE" ]]はエラーを吐かない

[[ 条件 ]] && { CMD1; CMDn; } || { CMDe1; CMDen; } 三項演算子

ファイルのテスト

-nt is newer than
-ot is older than
-ef have the same device and inode numbers

-b File is block special device (for files like /dev/hda1)
-c File is character special (for files like /dev/tty)
-d File is a directory
-e File exists
-f File is a regular file
-g File has its set-group-ID bit set
-h File is a symbolic link (same as -L)
-G File is owned by the effective group ID -k File has its sticky bit set
-L File is a symbolic link (same as -h) -O File is owned by the effective user ID -p File is a named pipe
-r File is readable
-s File has a size greater than zero
-S File is a socket
-u File has its set-user-ID bit set
-w File is writable
-x File is executable

-a and, -o or

  • 複合条件はこんな感じで\(\)を使って書く – if [ -r "$FN" -a \( -f "$FN" -o -p "$FN" \) ]

文字列比較

if [ "$VAR" ], if [ -z "$VAR" ] – 空判定

  • 前者は “has text”, 後者はis zero lengthをチェックする

一致比較, -eq=(の注意点)

  • -eqは空白や前ゼロを無視して比較する
VAR1=" 05 "
VAR2="5"

# これはtrue
if [ "$VAR1" -eq "$VAR2" ]

# これはfalse
if [ "$VAR1" = "$VAR2" ]

if [[ $VAR == パターンマッチ ]], if [[ $VAR =~ 正規表現条件 ]]

  • if [[ "${MYFILENAME}" == *.jpg ] – パターンマッチの例
  • shopt -s OPTIONする事でパターンマッチの挙動を変更できる
    • shopt -s extglob – 拡張パターンマッチを使う
    @( ... ) Only one occurrence
    *( ... ) Zero or more occurrences
    +( ... ) One or more occurrences
    ?( ... ) Zero or one occurrences
    !( ... ) Not these occurrences, but anything else
    
    • shopt -s nocasematch – 大文字小文字を区別しない
  • if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]] – 正規表現例
    • マッチした部分文字列は、BASH_REMATCHという配列に格納される

多岐分岐 case,

case $FN in
   *.gif) gif2png $FN  # パターンマッチは大文字小文字区別しない(したければ shopt -s nocasematch)
       ;;  # breakする
   *.png) pngOK $FN
       ;;
   *.jpg) jpg2gif $FN
       ;;
   *.tif | *.TIFF) tif2jpg $FN  # | はor条件
       ;;
   *) printf "File not supported: %s" $FN  # どの条件にもマッチしない場合
       ;;
esac

ループ

for 条件文

for f in /path/to/*

  • パス+ワイルドカード でマッチするファイル全件のループ

for (( i=0 ; i < 10 ; i++ )) – カウンタループ

  • 元はfor i in 1 2 3 4 5 6 7 8 9 10こう
  • for (( i=0, j=0 ; i+j < 10 ; i++, j++ )) 複数変数を使うことも可能
  • 小数を使いたければseqを使う(整数でも使えるが)
    • for fp in $(seq 1.0 .01 1.1)

while 条件

  • while [ -z "$LOCKFILE" ]
  • (( ))で算術評価式が書ける while (( COUNT < MAX ))
  • 入力を受け付けるループ while read READVAR, 入力可能な間は内部では 0 を返している
    • EOFが来たら -1 を返す
  • ファイル入力ループはこう書く
    • 後者のcat |を使うパターンはパイプを使ってるのでサブシェルとしてループが動く=ループ内で変数を操作してもループ外に影響が出ない(影響を及ぼすことが出来ない)
# ファイル入力ループ
while read lineoftext
do
  process that line
done < file.input

cat file.input | \
while read lineoftext
do
  process that line
done
svn status mysrc | \
while read TAG FN
do
    if [[ $TAG == \? ]]
    then
        echo $FN
        rm -rf "$FN"
    fi
done
  • 条件 が “trueの間=戻り値が0の間”だけループが回る
    • 1 はtrue扱い, while (( 1 )) は無限ループ ((( 1 )) は 0 を返している)

select – 選択メニュー

select v in ${ARR} do ... done

  • ARRの内容を元に選択メニューを表示する
  • 選択したindexが${REPLY}に、内容が${v}に設定される
DBLIST=$(sh ./listdb | tail +2)
select DB in $DBLIST
do
   echo Initializing database: $DB
   mysql -uuser -p $DB <myinit.sql
done
  • PS3をいじると、選択プロンプトをカスタマイズ出来る

出力, リダイレクト

echo

  • -n – 改行を出力しない
  • -e – 特殊文字を変換して出力
$ echo -e 'hi\c'
hi$

printf

$ printf '%s = %d\n' Lines  $LINES
Lines = 24

$ printf '%-10.10s = %4.2f\n' 'GigaHerz' 1.92735
GigaHerz   = 1.93

書式

  • %b,%s – 前者は¥nを改行として 扱う 。後者は扱わない("¥n"という文字列扱い)

CMD >& cmd.outとかCMD &> cmd.out – STDOUTとSTDERRを同じ出力先に出す

  • CMD > cmd.out 2>&1 この書き方よく見るけど、冗長だよね

{ CMD1; CMD2; CMDn; } > hoge.out, (CMD1; CMD2; CMDn) > hoge.out – 複数センテンス

  • {}, ()内の全コマンドの結果をリダイレクトする
    • {}抜きでCMD1; CMD2; CMDn > hoge.outと書くと、CMDnの処理結果しかリダイレクトされない
    • {}はコマンドのグルーピングとして機能している
    • ()は サブシェルが立ち上がる
  • {}, ()の違い
    • {}はコマンドの前後に空白が必要
    • {}は最終コマンドの後にも;が必要
    • ()はサブシェルで実行される
      • つまり別プロセスで実行される
      • { cd /tmp; ls } > hoge.outしたら実行後のpwdは/tmpになるが、(cd /tmp; ls) > hoge.out実行後のpwdは変わらない

ヒアドキュメント

<<EOF ... EOF

  • ↓このスクリプトは期待通り動かない
# ヒアドキュメント内ではデフォルトではエスケープが効いてない
# ので "$X" のような文字列は変数として認識される

grep $1 <<EOF
# name amt
pete $100
joe  $200
sam  $ 25
bill $  9
EOF
  • ヒアドキュメント内をエスケープしたければ、<<\EOFと “EOF”の前に”\”を付ける
    • もしくは'EOF'とシングルクォートで囲む
    • E\OFでも動く

<<-EOF ...

  • <<-EOFすることで、ヒアドキュメント内にインデントを書くことが出来る

プロセス置換

bashのプロセス置換機能を活用して、シェル作業やスクリプト書きを効率化する – 双六工場日誌

  • <(コマンドリスト) – コマンドの結果をファイルとして扱う
  • >(コマンドリスト) – 出力先をコマンドに渡す

ファイルディスクリプタ

[Bash]標準出力・標準エラー出力の全て(1>&2とか)まとめ | Coffee Breakにプログラミング備忘録

  • 1 – 標準出力
  • 2 – 標準エラー出力
  • 3以降 – 未割当

exec と併用して色々出来る

  • 出力先を変更する
# Optional, save the "old" STDERR
exec 3>&2

# Redirect any output to STDERR to an error log file instead
exec 2> /path/to/error_log

# script with "globally" redirected STDERR goes here
# Turn off redirect by reverting STDERR and closing FH3
exec 2>&3-
  • Net Redirection (curlやwgetっぽい通信をbashで行う)
# Finding My IP Address
exec 3<> /dev/tcp/www.ippages.com/80  # fd 3 の入出力をtcpに割当
echo -e "GET /simple/?se=1 HTTP/1.0\n" >&3  # GETリクエストを割り当てたfdにリダイレクト
cat <&3
  • プロセス置換との併用

入力

read -p "MSG " VAR – メッセージ付き入力プロンプト

  • ユーザにMSGを表示して入力を促し、入力内容をVAR変数に格納する
  • ↓こんな関数を用意して
function choice {
  CHOICE=''
  local prompt="$*"
  local answer
  read -p "$prompt" answer
  case "$answer" in
     [yY1] ) CHOICE='y';;
     [nN0] ) CHOICE='n';;
     *     ) CHOICE="$answer";;
  esac
} # end of function choice
  • こう呼ぶと便利かもしれない
choice "Do you want to look at the error log file? [Y/n]: "

read -s -p "MSG " PASSWD – パスワード用入力プロンプト

  • -sは文字のエコーイングをoffにするので、ユーザー入力の後に改行が表示できない
    • 回避策としてprintf "%b" "\n"とかすると良い
  • 入力したパスワード(を格納した環境変数)は、 メモリにplain textで乗っかる
    • /proc/coreから覗けちゃう

計算

expr 式, $(( 式 )), let 式 – 計算

let Y=(X+2)*10
Y=$(( ( X + 2 ) * 10 ))

(( 算術評価式 ))

  • 例えば変数の加算は…
    • これはエラー → $(( ${i}++ ))
    • これもエラー → (( ${i}++ ))
    • これが正 → (( i++ )) (算術評価式で変数を使うのに、その内容を展開しちゃうと 0++とか1++になっちゃう)
      • ((の前に$を付けない
      • 変数名に$を付けない
  • 複数の変数をまとめて加減算するときの注意 = letを使え
$(( x+=5 , y+=8 ))  # これはエラー( `$(( ))` は、別のコマンドの引数にするか、代入しないといけない)
let x+=5 y+=8  # こう書く。式の区切りはスペース

echo $(( x+=5 , y+=8 ))  # カンマ演算子は第2の式の値を返すので、こう書くと y の値がechoされる

awk "BEGIN {print \"The answer is: \" $* }";

  • awk BEGINブロックの$*に計算式を渡すと計算結果を出力する
function calc
{
   awk "BEGIN {print \"The answer is: \" $* }";
}

$ calc 2 + 3 + 4
The answer is: 9

$ calc (2+2-3)*4
-bash: syntax error near unexpected token `2+2-3'

$ calc '(2+2-3)*4'
The answer is: 4

$ calc \(2+2-3\)\*4
The answer is: 4

$ calc '(2+2-3)*4.5'
The answer is: 4.5

PATHhashコマンド

bash(csh)のhashとか言う、気づかないけど便利な機能 – それマグで!

Bashのコンソールで単語移動するショートカット(https://qiita.com/odacoh/items/b94be0deecaaa27b0263)

2018/2/17追記
1文字進める/戻る、直前/直後の1文字を削除、を追加した。


(Vimに慣れてしまうと)キーボードの矢印キーの利用はできるかぎり避けたくなる。
コンソールでは、bashのデフォルトでショートカットキーが設定されているのでそれを使う。

カーソル移動系

キー 動作
Ctrl + A カーソルを行頭へ
Ctrl + E カーソルを行末へ
Ctrl + B カーソルを1文字戻る
Ctrl + F カーソルを1文字進める
ESC + F カーソルを1単語先に進める
ESC + B カーソルを1単語戻す

カーソル位置から所定の文字列を削除

キー 動作
Ctrl + K カーソル位置から行末までを削除
Ctrl + U カーソル位置から行頭までを削除
Ctrl + h カーソル位置の直前の1文字を削除
Ctrl + d カーソル位置の直後の1文字を削除
Ctrl + W カーソル位置から単語の先頭までを削除
Ctrl + D カーソル位置の文字を削除

なお、このショートカットキーは、bash以外でも多くのMacアプリの入力フォームで利用できる。
(なぜか、Ctrl + Aは大抵効くが、Ctrl + Eは効かないことが多い)

おまけ

ESCをモディファイアキーとして使うのは辛いので、iTerm2のエスケープシーケンスでESC→optionに変更。
これにより以下のショートカットが利用できる。

キー 動作
Opt + F カーソルを1単語先に進める
Opt + B カーソルを1単語戻す

以上

参考
Macでターミナルを使うときはショートカットキーを覚えよう!!
http://yonchu.hatenablog.com/entry/20110214/1297662332
Mac のターミナルの Bash に単語単位カーソル移動のキーバインド設定をする
http://voidptr.seesaa.net/article/395408528.html

Bash(Zsh)上でよく使うカーソル移動などのショートカットを覚えると得する話

https://qiita.com/kamykn/items/5b7f3c3eb41a3549bb4e

きっかけ

最近他人のターミナルの画面を見る機会が多くなりまして、よく矢印キーだけでカーソル移動したりする方が多いなぁと感じたりするので、紹介用にまとめました。

また、これらのショートカットを覚えることで他のLinuxコマンドなどでも通用することも多いので、ぜひ覚えておいても損はないのかなと思います。

Bash(Zsh)に存在するEmacsモードとviモード

bash、Zshなどのカーソル移動にはEmacsモードとViモードが存在します。
これらのモードはカーソル移動におけるショートカットにおいて主に違いがあります。

これらのショートカットキーはreadlineというGNUのライブラリによって提供されています。(2017-09-25 13:11 コメントの指摘より追記)

(更にコメントの指摘より追記:2017-09-27 10:33) Zshに関してはZsh Line Editorとして別途実装しているようでした。
https://wiki.archlinux.org/index.php/zsh#Key_bindings

Zsh does not use readline, instead it uses its own and more powerful Zsh Line Editor, ZLE.

(–追記ここまで–)

大抵の場合BashやZshの場合、デフォルトのEmacsモードで事足りるかと思うので、今回はBashについてはEmacsモードについてまとめます。(Viモードについて気になる方は他の方の紹介しているViモードの記事をどうぞ)

Emacsモードのカーソル移動

ショートカット 意味
Ctrl + a カーソルを行頭に移動
Ctrl + e カーソルを行末に移動
Alt + → ※1 単語ブロック毎に右に移動 ※2
Alt + ← ※1 単語ブロック毎に左に移動 ※2

※1 Altは適宜メタキー(Escなど)に読み替えて下さい。以降Altが記載してあれば同じように読み替えて下さい。
※2 日本語に対しても使用できますが、基本的に英語に比べると、単語ブロックの判定の精度は落ちます。

Emacsモードの文字削除

文字削除も便利なショートカットが存在します

ショートカット 意味
Ctrl + h カーソル前の文字を削除
Ctrl + d カーソル位置の文字を削除
Ctrl + w 単語ブロック毎に削除
Ctrl + u カーソルから行頭まで削除
Ctrl + k カーソルから行末まで削除

ちなみに、Terminalでパスワードを入力する場面で打ち間違えたときに、Ctrl + uしたりするとパスワードを最初から打ち直したりできます。

Ctrl + w と Ctrl + h はVi(Vim)でも使えます。
Ctrl + hは地味ですが、ホームポジション崩したくない人(Vimmerとか)がよく使います[要出典]。

また、Bash、Zshにおいては行に文字が全く無い場合にはCtrl + dはexitと同じコマンドになります。

次候補、前候補

また、コマンドのヒストリーを遡る際の『候補列挙リストの移動』としての Ctrl+n Ctrl+p も同じです。

ショートカット 意味
Ctrl + n 前のヒストリーの候補へ
Ctrl + p 次のヒストリーの候補へ

この候補列挙のショートカットはVimでも補完の候補の列挙リストの移動などで利用します。

MySQLのCLIでも同様なキー操作が可能

これらのキー操作、CLIのMySQL操作でも一部同じショートカットをサポートしています。

MySQLのCLIもreadlineのライブラリによってショートカットが提供されているようです。(2017-09-25 13:11 コメントの指摘より追記)

ショートカット 意味
Ctrl + a カーソルを行頭に移動
Ctrl + e カーソルを行末に移動
Alt + → 単語ブロック毎に右に移動
Alt + ← 単語ブロック毎に左に移動
Ctrl + h カーソル前の文字を削除
Ctrl + d カーソル位置の文字を削除
Ctrl + u 行を削除
Ctrl + w カーソルから行頭まで削除
Ctrl + k カーソルから行末まで削除
Ctrl + n 前のヒストリーへ
Ctrl + p 次のヒストリーへ

Ctrl + w と Ctrl + uが若干惜しい感じですが、概ねサポートしています。

また、CLIのMySQLでもCtrl + dのショートカットによるexitをサポートしています。
ほかにも、Bash、Zshと同じようにCtrl + rによるヒストリー検索もサポートしてますよね。

追記:BashとMySQLのCLIでCtrl + u Ctrl + w のショートカットの実装が異なるのは
https://dev.mysql.com/doc/refman/5.6/ja/mysql-tips.html

Unix では、キーシーケンスは mysql のビルドに使用された入力ライブラリ (たとえば、libedit または readline ライブラリ) に依存します。

とのことでした。

これらのEmacsっぽいショートカットはMacならデフォルトで利用可能

MacはこのEmacsモードのターミナルのカーソル操作に影響を受けているっぽい(それか、Emacs自体に影響を受けているか)ので、Macではおおよそ同じショートカットが利用できますので覚えておいてきっと損はありません。

ショートカット 意味
Ctrl + a カーソルを行頭に移動
Ctrl + e カーソルを行末に移動
Alt + → 単語ブロック毎に右に移動
Alt + ← 単語ブロック毎に左に移動
Ctrl + h カーソル前の文字を削除
Ctrl + d カーソル後の文字を削除
Ctrl + k カーソルから行末まで削除
Ctrl + n 次の候補へ (※変換中)
Ctrl + p 前の候補へ(※変換中)

※Ctrl-uとCtrl-wがダメっぽいです(追記:Ctrl + u と Ctrl + w はreadlineにより提供されていないからでしょうか・・・。)

一部対応していないキーがありますが、概ね対応しているのではないかと思います。
但し、エディタによってはこれらのキーを上書きして別の機能を割り当ててしまっている場合があるのでご注意を…。

Viも色々と影響与えてますよ

ここまでEmacsのショートカットが多かったですが、Viのショートカットをサポートしているものも色々ありますよね。

カーソルの移動ではないですが、man--helpオプション や git diff で開くときに使われるlessなんかもViライクなショートカットをサポートしてますよね。

ちなみに、自分はこの記事を書くまでlessコマンドで開いてたということに気づいてなかったと言うのは内緒…(viにそういう開くモードが有るもんだとばっかり思ってました…)

ショートカット 意味
j 1行上に移動
k 1行下に移動
d 下にページ送り (※viだとノーマルモードでCtrl + d)
u 上にページ送り (※viだとノーマルモードでCtrl + u)
g ページ先頭へ (※viだとノーマルモードでgg)
G ページ終わりへ (※viだとノーマルモードでG)
/ ページ内検索の文字列入力開始
n 次のページ内検索結果へ
N 次のページ内検索結果へ

なお、lessの場合単にd,uではなくて、Ctrl + d, uでも元のショートカットと同じ挙動になります。
また、gもggも最終的には同じ場所にたどり着くので、vi使いは全く気にせず同じショートカットで使えるようになっていますよね。
qでlessコマンドを終了するのとかもviみたいですよね。

Viのショートカット体系のコマンド達

screenのコピーモードもViのようなショートカットコマンドをサポートしています。

ショートカット 意味
h 左へ
j 下へ
k 上へ
l 右へ
gg バッファ内先頭へ
G バッファ内末尾へ
Ctrl-u 半ページ上に移動
Ctrl-d 半ページ下に移動
/ 検索の文字列入力開始
n 次の検索結果へ
N 次の検索結果へ

他にもViと同じ動作をするコマンドが幾つかあります(^,$,w,b,eなど)

他にも、個人的にはtigとかよく使ったりしますが、こちらもviライクなコマンドラインをサポートしたりしてます。

たぶん、他にもたくさんあるんだろうなーと思いつつ、思いつき次第書き込む形式で追記していきたいと思います。それかコメントで教えて下さい (←えっ…)

おまけ

webの小ネタ系でViのhjklをショートカットとしてサポートしている場合も多いですが、個人的によく使うのは、

  • Google日本語入力でzh、zj、zk、zlでviの移動方向にあわせて各矢印が出る(←↓↑→)

いろいろなwebサービスでおもむろにhjklと叩くと色々と反応がある場合があって、『あぁ、意識してるんだな』感が感じられます。

まとめ

特にCLI系は新しいものに触れたときでも、Vi系やEmacs系のショートカットをサポートしているものも多いですので、特にマニュアル読まずに他で使えているショートカットを試してみるだけで意外と使えちゃったりします。
というわけで、ショートカットはEmacs系とVi系を少し覚えるだけでも決して損はないかと思いますので頑張って覚えましょう!

それでは皆さん、良いショートカットライフを!

※ この記事では便宜上Emacsライク、Viライクなショートカットというような表現をしてますが、Emacsやviが先に実装したのか、それとも他から影響を受けて、後から実装したのかについては検証しませんのでご了承下さい。

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク