NaClの野口です。

まず本記事内のクリップボードとはコピー、ペーストをする際に使用する一時領域のことを指します。

端末エミュレータ上での作業の際、クリップボードへ保存(コピー)する領域の選択にマウスを使用することがありますが、以下のような不満を私は感じています。

  • 意図した領域の選択を行うことが難しい
    • 選択領域に過不足があった場合の微調整が難しい
    • 疲れている時には特に難しく、またこの作業を行うことで疲労が更にたまる
  • 繰り返し作業が苦痛
    • 複数行のコピー、ペーストを複数回行う作業は考えるだけで嫌
    • マウス操作は自動化しづらいため楽が出来ない

上記のことを踏まえてマウスを極力使用せず、コマンドを使用してクリップボードを活用する方法について記載します。
また本記事はマウスに触れる時間を極力減らし、キーボードのみでクリップボードの操作を行うことを目標とします。

環境

動作環境はOSはUbuntu 16.10、シェルはzshを使用しています。
実行環境の詳しい情報を以下に記載します。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.10
DISTRIB_CODENAME=yakkety
DISTRIB_DESCRIPTION="Ubuntu 16.10"

$ echo $SHELL
/usr/bin/zsh

$ zsh --version
zsh 5.2 (x86_64-ubuntu-linux-gnu)

$ xsel --version
xsel version 1.2.0 by Conrad Parker <conrad@vergenet.net>

クリップボードを活用するためのコマンド

macOSにはクリップボードを操作するコマンドが標準で用意されています。

  • pbcopy
    • 標準入力から入力された内容をクリップボードに保存
  • pbpaste
    • クリップボードの内容を標準出力に出力

ただしUbuntuには上記のようなコマンドは標準で用意されていません。
そこで本記事ではxselで代用します。 xselapt-getコマンドを実行することで簡単にインストール出来ます。

$ sudo apt-get install -y xsel

xselの基本的な使い方を以下に示します。

注: ##で始まる行についてはコマンドについてのコメントであり、コマンドの出力結果ではありません。

## テスト用テキストファイルの内容を表示
$ cat /tmp/clipboard_test.txt
Test of xsel command.
xselコマンドのテスト。
## テキストファイルの内容をクリップボードにコピー
$ cat /tmp/clipboard_test.txt | xsel --clipboard --input
## クリップボードの内容を出力
$ xsel --clipboard --output
## クリップボードをクリア
$ xsel --clipboard --clear
## クリップボードがクリアされたことを確認
$ xsel --clipboard --output

私は上記コマンドを利用しやすいように、~/.zshrc内に以下のようなaliasを定義しています。

alias pbcopy='xsel --clipboard --input'
alias pbpaste='xsel --clipboard --output'

: 次節以降コマンドの利用例を示す際、上記alias(pbcopypbpaste)を使用します。

コマンドの利用例

前述しましたがpbcopyは標準入力から入力された内容をクリップボードに保存します。
つまり任意のコマンドの標準出力を、パイプを使用してpbcopyの標準入力にリダイレクトすればいいということです。
上記よりコマンドを使用して意図した内容を標準出力に出力する方法を知っておく必要があることが分かります。
ですが裏を返せば意図した内容を標準出力に出力する方法を身に付ければ、クリップボードを思うがままに操作することが可能になるということです。

前置きが長くなりましたが、本節ではpbcopypbpasteの利用例について記載します。
また各コマンド実行後にクリップボードの内容を確認するために、pbpasteを実行しています。

注: ##で始まる行についてはコマンドについてのコメントであり、コマンドの出力結果ではありません。

ファイルの内容をクリップボードに保存

catを使用します。

$ cat /tmp/clipboard_test.txt | pbcopy
$ pbpaste
Test of pbcopy.
pbcopyのテスト。

行番号を付けたい場合はnlを使用します。
ただしnlはオプション-b aを付けないと空行には行番号をつけないため注意してください。

$ nl -b a /tmp/clipboard_test.txt | pbcopy
$ pbpaste
     1  Test of pbcopy command.
     2  pbcopyコマンドのテスト。
## 行頭の空白を削除する
$ nl -b a /tmp/clipboard_test.txt | sed -e 's/^\s\+//' | pbcopy
$ pbpaste
1       Test of pbcopy.
2       pbcopyのテスト。
## 行頭の空白を削除し、行番号の後の空白を2つにする
$ nl -b a -s '  ' /tmp/clipboard_test.txt | sed -e 's/^\s\+//' | pbcopy
$ pbpaste
1  Test of pbcopy.
2  pbcopyのテスト。

ファイルの任意の行をクリップボードに保存

sedを使用します。

## ~/.vim/vimrc の38〜42行目
$ sed -ne '38,42p' ~/.vim/vimrc | pbcopy
$ pbpaste
augroup auto_comment_off
    autocmd!
    autocmd BufEnter * setlocal formatoptions-=r
    autocmd BufEnter * setlocal formatoptions-=o
augroup END
## ~/.vim/vimrc の3行目、101〜102行目、最終行
$ sed -ne '3p; 101,102p; $p' ~/.vim/vimrc | pbcopy
$ pbpaste
scriptencoding utf-8
nnoremap <Leader>w :w<CR>
nnoremap <Leader>q :q<CR>
vmap gx <Plug>(openbrowser-smart-search)
## ~/.vim/vimrc内の「auto_comment_off」にマッチする行から「END」にマッチする行
$ sed -ne '/auto_comment_off/,/END/p' ~/.vim/vimrc
$ pbpaste
augroup auto_comment_off
    autocmd!
    autocmd BufEnter * setlocal formatoptions-=r
    autocmd BufEnter * setlocal formatoptions-=o
augroup END

行番号を付けたい場合はnlの標準出力をsedの標準入力へリダイレクトします。

## ~/.vim/vimrc の3行目、101〜102行目、最終行(行番号付き)
$ nl -b a ~/.vim/vimrc | sed -ne '3p; 101,102p; $p' | pbcopy
$ pbpaste
     3  scriptencoding utf-8
   101  nnoremap <Leader>w :w<CR>
   102  nnoremap <Leader>q :q<CR>
   638  vmap gx <Plug>(openbrowser-smart-search)

ファイル内を検索し、マッチした前後の行をクリップボードに保存

grepを使用します。
-B mオプションによりマッチした行から前m行、-A nオプションによりマッチした行から後n行を表示できます。
行番号はnlを使用する方法の他に、grep-nオプションを付ける方法があります。

## ~/.zshrc内の「alias la」にマッチする行とマッチした行から前3行、後2行
$ grep -B 3 -A 2 'alias la' ~/.zshrc | pbcopy
$ pbpaste
alias tmux="TERM=screen-256color-bce tmux"
alias v="vim"
alias l="ls"
alias la="ls -a"
alias lf="ls -F"
alias ll="ls -l"
## ~/.zshrc内の「alias la」にマッチする行とマッチした行から前3行、後2行
$ grep -n -B 3 -A 2 'alias la' ~/.zshrc | pbcopy
$ pbpaste
169-alias tmux="TERM=screen-256color-bce tmux"
170-alias v="vim"
171-alias l="ls"
172:alias la="ls -a"
173-alias lf="ls -F"
174-alias ll="ls -l"

ブラウザ上のサンプルコードの一部を変更してファイルを作成

ユーザ名、会社名などがコード内に混ざっている場合、それらの文字列を別の文字列で置換する作業が必要です。
ブラウザ上のサンプルコードをクリップボードにあらかじめコピーしておき、以下のコマンドを実行します。

## 「ユーザ名」という文字列を「takuya」に変更し、/tmp/output.txt に保存する
$ pbpaste | sed -e 's/ユーザ名/takuya/' > /tmp/output.txt
## ファイルの内容の出力は割愛します

おわりに

簡単にですが、pbcopypbpasteを使用したクリップボードの活用について記載しました。
本記事で数多くの便利なコマンドの内のほんの僅かしか紹介していません。
興味を持った方は各自で調べていただけると幸いです(私は「逆引きUNIXコマンド - Linuxと過ごす」をよく閲覧します)。

余談ですが、私がワンライナーを書く作業が非常に好きです。その理由は大きく分けて4つあります。

  1. パズルを解くような楽しみがある
    • 各コマンドを連結して自分の求める結果を取得できた時に大きな喜びを感じる
    • 書く人によって解き方が大きく異なる
      • 他の人のワンライナーを見ることで感動することが多い
  2. 新しいコマンドを覚えることで出来ることが大きく拡がる
    • 本記事ではpbcopypbpasteを使用することでクリップボードを活用することが出来た
  3. デバッグが楽
    • ワンライナーは基本的に小さなものを組み立てて大きな目的を達成する
    • 各コマンドの出力を随時見ることが出来るため、最終段階で大きな壁に突き当たることが少ない
      • 小さな壁をその都度乗り越えていくイメージ
  4. 方針変更する際のコストが低い
    • 各コマンドが直交しているため
    • 例としてファイルの各行を先頭から処理していたところを末尾から処理するように変更したい場合
      • 行単位の処理の場合、catでファイルを読んでいたところをtacを使用するように変更
      • 文字単位の処理の場合、cattacに変更し結果をrevにリダイレクトするように変更

以上長くなりましたが、これからも楽しみながら技術力を向上していきたいです。
最後まで読んでいただきありがとうございました。

参考サイト