tailコマンドで行頭からN行目以降を出力

tailコマンドと言えばファイルの最終行から指定行文を出力しますが、
実は行頭から指定行以降の内容を出力することもできます。
以下がコマンド例です。

$ tail -n +10 test.txt

上記はtest.txtの行頭から10行目以降を出力します (10行目を含む)。
このように”-n”オプションと”+N”を指定することで実現できます。
なお”-c”オプションにするとバイト数指定になります。
また”+”記号を”-“にすると行末から指定行分を出力する、
従来のtailコマンドの動作になります。

joinコマンドの使い方

joinコマンドの基本的な使い方のメモです。
joinコマンドを使えば二つのファイルのレコードを結合し、
一つのファイルにまとめることができます。
※本記事では中間ファイルを作成したくないため、ワンライナーで記載します。

例として次のような二つのファイルを用意します。

## items: ID, 商品名, 値段
$ cat items
1 car 1,000,000
5 cup 200
3 flower 50
11 display 50,000
4 desk 9,000
6 chair 4,000

## orders: ID, 注文数
$ cat orders
11 3
5 100
3 2
1 1
55 3
61 2

joinにかけるにはsortされている必要があるため、それぞれsortします。

$ awk '{printf "%02d ", $1; print $2, $3}' items | sort
01 car 1,000,000
03 flower 50
04 desk 9,000
05 cup 200
06 chair 4,000
11 display 50,000

$ awk '{printf "%02d ", $1; print $2}' orders | sort
01 1
03 2
05 100
11 3
55 3
61 2

これらをjoinで結合し、以下の形式で出力します。
ID, 商品名, 値段, 注文数
なおjoinは一番左の列をkeyとして結合します。

$ join -a 1 -e 0 -o 1.1 1.2 1.3 2.2 <(awk '{printf "%02d ", $1; print $2, $3}' items | sort) <(awk '{printf "%02d ", $1; print $2}' orders | sort)
01 car 1,000,000 1
03 flower 50 2
04 desk 9,000 0
05 cup 200 100
06 chair 4,000 0
11 display 50,000 3

joinで使っている各オプションを解説します。

  • -a 1
    • 二つのファイルを突き合わせしてマッチするkeyがない場合、どちらのファイルを優先出力するか
    • 本例は1つめの入力ファイル (items) を優先
  • -e 0
    • 欠損値をどういった文字列で埋めるか
    • 本例は0で埋める
  • -o 1.1 1.2 1.3 2.2
    • 出力形式の指定
    • “1.1”と記載すると”1ファイルめ (items) の1列目”という意味になる

最後にcolumnコマンドを使い見た目を整えます。

$ join -a 1 -e 0 -o 1.1 1.2 1.3 2.2 <(awk '{printf "%02d ", $1; print $2, $3}' items | sort) <(awk '{printf "%02d ", $1; print $2}' orders | sort) | column -t
01  car      1,000,000  1
03  flower   50         2
04  desk     9,000      0
05  cup      200        100
06  chair    4,000      0
11  display  50,000     3

この通り、簡単なファイル間のレコード結合であればjoinで済みそうです。

lsofを使った各プロセスの通信ポート確認

各プロセスが使用しているポート番号を確認したい場合
netstatを使うことが多いと思いますが、
最近lsofコマンドでも手軽に調べられると知りました。

## 各プロセスが使用しているポート番号を漏れなく列挙
$ lsof -i


## 特定のポート番号を使用しているプロセスを表示
$ lsof -i:22      # 22番ポートを使用しているプロセス

$ lsof -itcp:22   # TCP 22番ポートを使用しているプロセス

$ lsof -i4tcp:22  # IPv4 TCP 22番ポートを使用しているプロセス


## 特定のプロセスが使用しているポート番号を表示
$ lsof -c sshd | egrep "TCP|UDP"            # プロセス名で指定

$ lsof -p <port number> | egrep "TCP|UDP"   # PIDで指定

lsofが入っていれば、そちらを使う方が簡単ですね。

Linuxのwatchコマンド

watchコマンドを使うと指定したコマンドを定期的に実行し、
実行結果の変化を確認することができます。

$ watch -d date

例えば上記を実行すると2秒ごとにdateコマンドを実行し、
表示される時間が刻々と変化していく様子を確認できます。
またdオプションをつけることで出力の変化した箇所を
ハイライトしてくれます。
なおnオプションで実行間隔を任意に指定できます (デフォルトは2秒)。

繰り返し実行し、出力の変化を確認したいときに使えそうです。

nc (netcat) コマンドを使ったNW疎通確認

最近ネットワークまわりの構築を仕事で行う機会があったのですが、
そのときに知ったnc (netcat) コマンドが思いの外便利だったので
簡単にメモを残しておきます。

クライアントとして対象サーバへ接続

接続対象サーバのIPアドレスとポート番号を指定し、
クライアントとして接続しに行きます。
例えばIPアドレスが 192.168.0.33 のサーバの
22番ポートの疎通確認は以下の通りです。

$ nc -v 192.168.0.33 22
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 192.168.0.33:22.
SSH-2.0-OpenSSH_6.7p1 Raspbian-5+deb8u3

上記は自宅にあるRaspberry Piに接続したときの結果です。
レスポンスを見て分かる通り、22番ポートが開いていて
SSHサーバがLISTENしていると分かります。

サーバとして指定ポートでLISTEN

ncを使えば任意のポートでLISTENすることが可能です。
1521番ポートでLISTENする際は以下のようにします。

$ nc -vl 1521

すでに他のサービスがLISTENしている場合は
“nc: Address already in use”と返ってきます。

またサーバ側でLISTENしている状態で
クライアントから同じポートへ繋ぎにいくと、
そのポートで通信可能か確認できます。

例えばサーバ側が1521番ポートでLISTENしている場合、
クライアント側では以下のようになります。

$ nc -v 192.168.0.33 1521
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 192.168.0.33:1521.

一方サーバ側では以下のようになります。

$ nc -vl 1521
Listening on [0.0.0.0] (family 0, port 1521)
Connection from [192.168.0.36] port 1521 [tcp/*] accepted (family 2, sport 64535)

この状態でクライアント or サーバ上で文字列を入力しEnterキーを押下すると、
もう一方の端末に文字列が送信されます。

クライアントからポートスキャンのみ実施

これまでに紹介した接続方法の他に、ポートスキャンのみ実施して
ポートが開いているかどうか確認する方法もあります。
例えばIPアドレスが 192.168.0.33 のサーバの
7000-7010番ポートをスキャンする場合は以下のようにします。

$ nc -zv 192.168.0.33 7000-7010

ただしncコマンドのポートスキャン機能 (zオプション) は
REHL7系からなくなってしまいましたので、
ポートスキャンしたい場合はnmapを使いましょう。

システムのパフォーマンス情報収集メモ

はじめに

システムのパフォーマンスについて勉強する機会があったので、
パフォーマンス情報の取得方法について簡単にメモ。

パフォーマンス情報の取得方法

一定間隔のサマリ情報

※サマリ情報を確認する場合、最初の一行目は
 起動時からのサマリ情報となるため無視する

  • sar
    • 情報:CPU、メモリ、Disk IOの仕様状況
root# sar -ubr 3 3
Linux 3.10.0-514.6.1.el7.x86_64 (test.sample.com)   2017年11月19日     _x86_64_    (2 CPU)

22時23分24秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
22時23分27秒     all      1.69      0.00      0.51      0.00      0.00     97.80

22時23分24秒       tps      rtps      wtps   bread/s   bwrtn/s
22時23分27秒      1.00      0.00      1.00      0.00     34.67

22時23分24秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
22時23分27秒    280468   3585084     92.74      1848   2371256   4523820     56.13   1573332   1741284        64

22時23分27秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
22時23分30秒     all      2.20      0.00      0.68      0.00      0.00     97.12

22時23分27秒       tps      rtps      wtps   bread/s   bwrtn/s
22時23分30秒      0.66      0.00      0.66      0.00     21.26

22時23分27秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
22時23分30秒    280372   3585180     92.75      1848   2371256   4523820     56.13   1573340   1741284        64

22時23分30秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
22時23分33秒     all      2.38      0.00      0.85      0.00      0.00     96.77

22時23分30秒       tps      rtps      wtps   bread/s   bwrtn/s
22時23分33秒      0.67      0.00      0.67      0.00     21.33

22時23分30秒 kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
22時23分33秒    280100   3585452     92.75      1848   2371256   4523788     56.13   1573340   1741284        68
  • vmstat
    • 情報:CPU、メモリ、Disk IOの使用状況
root# vmstat 3 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 4  0      0 264772   1848 2478080    0    0   366    23  415  807  3  2 93  2  0
 0  0      0 265028   1848 2478080    0    0     0    77  799 1554  4  1 96  0  0
 1  0      0 264780   1848 2478084    0    0     0    11  841 1635  3  1 95  1  0
  • iostat
    • 情報:各ディスクの読み書き速度、待ち数など
root# iostat -x 3 2
Linux 3.10.0-514.6.1.el7.x86_64 (test.sample.com)   2017年11月19日     _x86_64_    (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.74    0.00    1.55    1.95    0.00   93.76

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.02     0.27    9.23    3.39   642.08    41.37   108.31     0.26   20.97   20.52   22.19   3.71   4.68
dm-0              0.00     0.00    0.13    0.00     1.62     0.00    25.02     0.00    1.06    1.06    0.00   0.74   0.01
dm-1              0.00     0.00    0.03    0.00     0.23     0.00    18.00     0.00    1.82    1.82    0.00   1.82   0.00
dm-2              0.00     0.00    0.03    0.00     0.38     0.00    27.69     0.00    2.51    2.51    0.00   1.53   0.00
dm-3              0.00     0.00    0.03    0.00     0.38     0.00    27.69     0.00    1.99    1.99    0.00   1.57   0.00
dm-4              0.00     0.00    0.03    0.00     0.38     0.00    27.69     0.00    1.11    1.11    0.00   0.94   0.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.04    0.00    0.85    0.00    0.00   97.10

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00    0.67     0.00    10.67    32.00     0.00    1.50    0.00    1.50   1.50   0.10
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-1              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-2              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-3              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-4              0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

その瞬間の情報

  • ps
    • 情報:その瞬間の起動プロセス情報
root# ps -ef
・・・
oracle     6203      1  0 22:25 ?        00:00:00 ora_j001_orcl
oracle     6205      1  0 22:25 ?        00:00:00 ora_j002_orcl
postfix    6248   2499  0 22:25 ?        00:00:00 cleanup -z -t unix -u
postfix    6253   2499  0 22:25 ?        00:00:00 trivial-rewrite -n rewrite -t unix -u
postfix    6256   2499  0 22:25 ?        00:00:00 local -t unix
postfix    6257   2499  0 22:25 ?        00:00:00 local -t unix
・・・
  • top
    • 情報:その瞬間の起動プロセスと各プロセスごとのリソース使用状況
root# top -b -n 1
top - 22:26:29 up 44 min,  2 users,  load average: 0.01, 0.05, 0.14
Tasks: 261 total,   1 running, 260 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.7 us,  1.5 sy,  0.0 ni, 93.9 id,  1.9 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem :  3865552 total,   275000 free,  1111032 used,  2479520 buff/cache
KiB Swap:  4194300 total,  4194300 free,        0 used.  1721444 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  3410 root      20   0 2012416 232756  48284 S  18.8  6.0   1:30.87 gnome-shell
  2501 root      20   0  251128  42628  10716 S   6.2  1.1   0:25.43 Xorg
     1 root      20   0  125372   3860   2388 S   0.0  0.1   0:02.11 systemd
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd
     3 root      20   0       0      0      0 S   0.0  0.0   0:00.09 ksoftirqd/0
     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
     7 root      rt   0       0      0      0 S   0.0  0.0   0:00.09 migration/0
・・・
  • pstack
    • 情報:指定したプロセスがその瞬間に実行している
         コールスタック情報
root# pstack 4088
 #0  0x00007ff351cfcfca in semtimedop () from /lib64/libc.so.6
 #1  0x000000000cd9362d in sskgpwwait ()
 #2  0x000000000cd90f98 in skgpwwait ()
 #3  0x000000000c8ddeab in ksliwat ()
 #4  0x000000000c8dd2b1 in kslwaitctx ()
 #5  0x0000000000c2e59c in kslwait ()
 #6  0x00000000013b38eb in ktmmon ()
 #7  0x00000000013ae020 in ktmSmonMain ()
 #8  0x0000000002e519ec in ksbrdp ()
 #9  0x00000000030eca40 in opirip ()
 #10 0x0000000001b9bd68 in opidrv ()
 #11 0x00000000026ac2d1 in sou2o ()
 #12 0x0000000000ba8bbe in opimai_real ()
 #13 0x00000000026b6a1c in ssthrdmain ()
 #14 0x0000000000ba8a8c in main ()

詳細な処理の記録情報

  • tcpdump
    • 情報:NW上を流れるパケット情報の記録
root# tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:36:28.976861 IP 192.168.0.33.ssh > 192.168.0.36.61838: Flags [P.], seq 405791128:405791368, ack 3704156114, win 294, length 240
13:36:29.024540 IP 192.168.0.36.61838 > 192.168.0.33.ssh: Flags [.], ack 240, win 254, length 0
13:36:29.932405 IP 192.168.0.33.44348 > 192.168.0.1.domain: 4654+ PTR? 33.0.168.192.in-addr.arpa. (43)
13:36:29.936219 ba:27:eb:ee:1d:10 (oui Unknown) > b8:27:eb:ee:1d:10 (oui Unknown), ethertype Unknown (0x886c), length 153:
        0x0000:  8001 00b7 0000 1018 0001 0002 0000 0000  ................
        0x0010:  002c 0000 0000 0000 0000 0000 0000 0000  .,..............
        0x0020:  004f f0d5 bff2 0a12 776c 3000 0000 0000  .O......wl0.....
・・・
  • strace
    • 情報:指定したプロセスのシステムコールの記録
root# strace -p 4080
Process 4080 attached
times(NULL)                             = 429775225
semtimedop(589832, {{16, -1, 0}}, 1, {2, 920000000}) = -1 EAGAIN (Resource temporarily unavailable)
getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 51616}, ru_stime={0, 531645}, ...}) = 0
getrusage(0x1 /* RUSAGE_??? */, {ru_utime={0, 51617}, ru_stime={0, 531660}, ...}) = 0
times(NULL)                             = 429775517
times(NULL)                             = 429775517
・・・

おわりに

実際にパフォーマンス問題が起きて調査する際は、
上記にあげたツールを組み合わせて原因追求していきます。
そのためには日頃から適切な情報収集をしておく必要がありますね。

Windows Subsystem for Linuxとコマンドプロンプトの連携

はじめに

Windows10上でUbuntuやOpenSUSEといったLinuxディストリビューションを
利用できるWindows Subsystem for Linux (WSL) ですが、
Fall Creators Updateからβ版ではなく正式な機能となりました。
それに伴い、β版では別のアプリケーションとして動かしていたWSLを
コマンドプロンプトから直接呼び出せるようになりました。
また逆にWSLからコマンドプロンプトを呼び出すこともできます。
さらにコマンドプロンプトの出力結果をWSLのコマンドへパイプで
渡すこともできます(逆も可能)。

今回はコマンドプロンプトからWSLの呼び出し、
そしてWSLからコマンドプロンプトの呼び出しを試してみました。

コマンドプロンプトからWSLの呼び出し

“wsl”と実行することで既定に設定されている
Linuxディストリビューションが起動します。

C:\Users\test>wsl
test@PC01:/mnt/c/Users/test>

既定に設定されているディストリビューションは
“wslconfig”コマンドで確認できます。

C:\Users\test>wslconfig /list
Windows Subsystem for Linux ディストリビューション:
openSUSE-42 (既定)
Ubuntu

コマンドプロンプトからLinuxの特定コマンドのみを
呼び出すこともできます。

C:\Users\test>wsl cat /etc/os-release
NAME="openSUSE Leap"
VERSION="42.3"
ID=opensuse
ID_LIKE="suse"
VERSION_ID="42.3"
PRETTY_NAME="openSUSE Leap 42.3"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:leap:42.3"
BUG_REPORT_URL="https://bugs.opensuse.org"
HOME_URL="https://www.opensuse.org/"

コマンドプロンプトの出力結果をWSLのコマンドに渡してみます。

C:\Users\test>dir | wsl grep Do
2017/10/22  13:13    <DIR>          Documents
2017/11/11  14:53    <DIR>          Downloads

WSLからコマンドプロンプトの呼び出し

WSLからコマンドプロンプトのコマンドを呼び出す際は
“cmd.exe”のように”exe”まで指定します。

test@PC01:~> cmd.exe
Microsoft Windows [Version 10.0.16299.19]
(c) 2017 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>

また特定のコマンドのみを呼び出すこともできます。

test@PC01:~> cmd.exe /c vol
 Volume in drive C is Windows
 Volume Serial Number is FEC5-3714

WSLの出力結果をコマンドプロンプトのコマンドへ渡してみます。

test@PC01:~> cat /etc/os-release | cmd.exe /c sort
ANSI_COLOR="0;32"
BUG_REPORT_URL="https://bugs.opensuse.org"
CPE_NAME="cpe:/o:opensuse:leap:42.3"
HOME_URL="https://www.opensuse.org/"
ID_LIKE="suse"
ID=opensuse
NAME="openSUSE Leap"
PRETTY_NAME="openSUSE Leap 42.3"
VERSION_ID="42.3"
VERSION="42.3"

おわりに

今回ご紹介したようにコマンドプロンプトとの連携など、
WSLはFall Creators Updateを経てパワーアップしています。
普段からLinuxに慣れ親しんでいる方は
結構な恩恵を受けられるのではないでしょうか。

ddコマンドの使い方

はじめに

ddコマンドの使い方をいつも忘れてしまうので、
この機会に書き留めておきます。

ddコマンドの基本オプション

  • if
    • 入力ファイル(デバイス)を指定
    • 指定がなければ標準入力が入力となる
  • of
    • 出力ファイル(デバイス)を指定
    • 指定がなければ標準出力が出力となる
  • bs
    • 入出力のブロックサイズを指定
    • 入力と出力で異なるブロックサイズを指定する場合は
      “ibs” (入力)と”obs” (出力) で指定
  • count
    • コピーするブロック数を指定

上記を踏まえた上で以下に使用例を示します。

使用例

※以降のコマンドは全てrootユーザで実行します。

DVDやHDDなどのディスクを他のディスクへコピー

[root] dd if=/dev/sda1 of=/dev/sdb1

DVDやHDDなどのディスクをISOファイルとして保存

## 入力デバイス名は環境によって異なります
[root] dd if=/dev/sr0 of=/tmp/backup.iso

ISOファイルをディスクに焼く場合は”if”と”of”を逆にします。

ちなみに作成したISOファイルをマウントする際は以下のようにします。

## &quot;/tmp/backup.iso&quot; を &quot;/mnt/&quot; にマウント
[root] mount -o loop -t iso9660 /tmp/dvd.iso /mnt/

任意サイズのファイルを作成

## 以下の例ではブロックサイズを 1kb にした上で 10mb のファイルを作成
[root] dd if=/dev/zero of=dummy.out bs=1024 count=10240

上記はとにかく大きいサイズのファイルが欲しい場合や、
ストレージI/Oの性能値を取得する際に有用です。

おわりに

こうして整理してみると、知っていれば
いざというときに助かるコマンドだな、と改めて思いました。
これでもう忘れることはないはず…!

bash上の作業を効率化するキー操作

はじめに

普段私が使っているbash上のキー操作について紹介します。
中には誰でも知っている基本的なものもありますが、
いずれも使えるようになると作業効率がアップすること間違いなしです。

なお今回紹介するものはemacsキーバインドが設定されていることを
前提としています。
(個人的にはviキーバインドが好きなんですが、かなりマイナーなので)

また紹介するコマンド中の”C”は”Control”キーを意味し、
“,”(カンマ)区切りのコマンドは左のコマンドのあとに入力します。

移動

  • C-f
    • カーソルを一文字右に進める
  • C-b
    • カーソルを一文字左に進める
  • C-a
    • カーソルを行頭に移動させる
  • C-e
    • カーソルを行末に移動させる
  • C-[, f
    • カーソルを一単語分右に移動させる
  • C-[, b
    • カーソルを一単語分左に移動させる

補完

  • Tab, Tab
    • 入力した文字列にマッチするコマンド、ファイル名で補完する
    • 候補が一つに絞れない場合は候補を標準出力に列挙する
  • C-x, !
    • 入力した文字列にマッチするコマンド名で補完する
    • 候補が一つに絞れない場合は候補を標準出力に列挙する
  • C-x, /
    • 入力した文字列にマッチする、カレントディレクトリ内の
      ディレクトリ名、もしくはファイル名で補完する
    • 候補が一つに絞れない場合は候補を標準出力に列挙する
  • C-x, @
    • 入力した文字列にマッチするホスト名で補完する
    • 補完対象となるホスト名は”/etc/hosts”に書いてあるもの
    • 候補が一つに絞れない場合は候補を標準出力に列挙する

削除

  • C-h
    • カーソルの左にある文字を一文字消す
  • C-w
    • カーソル位置から左にある最寄りのスペースまでの文字列を消す
    • 消した文字列はキルバッファに入る
    • 行を変えない限り、キルバッファにはスタック形式で
      文字列が追記される?
  • C-[, C-h
    • カーソル位置から左にある単語を一単語分消去する
    • 単語の区切りは”_”(アンダーバー)、”/”(スラッシュ)などの記号や
      スペースを使えるっぽい
    • 消した文字列はキルバッファに入る
    • 行を変えない限り、キルバッファにはスタック形式で
      文字列が追記される?
  • C-u
    • カーソル位置から左にある文字列を行頭まで全て消す
    • 消した文字列はキルバッファに入る
    • 実行する度にキルバッファの内容は入れ替えられるっぽい

コピペ

  • C-y
    • キルバッファに入っている文字列を貼り付ける
  • C-[, .(ドット)
    • 直前に実行したコマンドの引数のうち、一番最後のものを呼び出す
    • “cp”したあとに”ls”する、といった場合の作業効率がグンと上がります
  • マウスカーソルで文字列を選択, マウスの中央ボタンを押す
    • キー操作ではないですが、手っ取り早いコピペ手段として
      よく使います
    • 恐らくだいたいのターミナルソフトで使えると思います
    • 右クリックしてコピー、貼り付けとかしなくて良いので、
      地味に作業効率がアップします
    • ちなみにマウスで文字列選択する際は、ダブルクリックすると
      良い感じに自動で選択してくれます(改行には要注意です)
  • マウスカーソルで文字列を選択、Shift+Insert
    • 上記と同じです

履歴

※履歴関連のコマンドはターミナルログが汚くなるので
 使用の際は注意が必要です。

  • C-p
    • 以前実行したコマンドを呼び出す
    • 連続して押すことでコマンド履歴を一つずつ辿れます
  • C-n
    • “C-p”の逆の操作です
  • C-r, 検索文字列を入力
    • 以前実行したコマンドから、
      入力した文字列に対応するものを呼び出す
    • コマンド名だけでなくオプションやファイル名といった引数も
      検索対象です
    • “C-r”を連続して押すことで次の候補へ一つずつ辿れます
    • “C-q”を連続して押すことで”C-r”と逆の操作ができます
    • ちなみに”C-q”は別のコマンドが
      アサインされている可能性が大なので、
      以下のコマンドを事前に入力しておくと良いです
      “$ stty stop undef”

おわりに

以上、私が普段からbash上の作業で使っている
キー操作を紹介しました。
まだまだ便利なものがあると思いますので、
見つけ次第、随時更新したいと思います。

Vimの外部コマンド連携

久々にVimネタで書きます。
今回はVimの外部コマンド連携についてです。
Vimといえばターミナル内で起動してテキスト編集できることが
大きな売りの一つですが、それをVimの特徴たらしめている要素が
「外部コマンド連携」機能だと思っています。

と言いつつも、お恥ずかしいことに最近まで外部コマンド連携については
“!”を使えばシェルのコマンドを実行できる、くらいの認識でした。

しかしそこには標準出力をバッファに取り込む(“r!”)であったり、
バッファを標準入力に書き出す(“w !”)といった使い方もある訳で。
その辺りについて備忘録的に書いていきます。

外部コマンドの起動

まずは標準的な使い方から。
“:!”と入力することでVimから外部コマンドを起動できます。

## &quot;:!&quot;のあとにシェルのコマンドを入力
:!&lt;command name&gt;

## 例えばVimを起動したままCのコンパイルをしたり
:!make

## gitリポジトリにcommitしたりできます
:!git commit -a -m &quot;test&quot;

## 編集中のファイルのバックアップも気軽に作れます
## ちなみに&quot;%&quot;は編集中のファイル名を表します
:!cp % %.bak

私は最近まで上記くらいの使い方しか知らなかったです…

外部コマンドの標準出力をバッファへ取り込む

“:r!”を使うと外部コマンドの標準出力を
バッファに取り込むことが出来ます。

## 例えばテキスト中に日付を入れてみたり
## (%記号を使う場合はエスケープ文字&quot;\&quot;が必要っぽいです)
:r!date +&quot;\%Y/\%M/\%d \%H:\%m:\%S&quot;

## ワークディレクトリまでの絶対パスを挿入したいときにも
:r!pwd

## 特定ディレクトリ内のファイル一覧を作成したり出来ます
:r!ls -1

外部コマンドの標準入力にバッファの内容を渡す

“:w !”を使うと外部コマンドにバッファの内容を
標準入力として渡すことができます。
※”w”と”!”の間には必ず一スペース必要です

## バッファ内から条件に合うものだけを取り出してみたり
:w !egrep &quot;^2017-08-20&quot; | less

## バッファ内の計算式から計算結果を出してみたり
:w !bc -l

うーん、あまり良い例を思いつかなかったです。

編集中バッファを外部コマンドにより整形

“%!”コマンドは編集中バッファの内容を外部コマンドの
標準入力として渡し、その実行結果をバッファとして取り込みます。

## csvファイルをVimで編集中(あるかな?)にawkでフィルタ
:%!awk -F, '$2==&quot;test&quot;{print $0}'

## 編集中バッファの特定範囲だけを数値でソート
'&lt;,'&gt;%!sort -n

またソートについてはVimの機能として強力なものがあるので、
別の機会に是非ご紹介したいです。

おわりに

久々のVim関連のポストでしたが、
Vimの世界は奥深く広いものですね。
知らないことが未だたくさんありそうです。
他にも目からウロコな発見があれば記事にしていく所存です。