末尾ひとつ前のフィールドを取得

`awk`で表題の通り。

■ 環境

  • awk 3.1.7
  • CentOS 6.7

■ awk

`awk`で末尾のフィールドの値を取得することがある。例えば下記のようなCSVである場合。

$ cat test.csv
1,aaa,bbb,ccc
2,aiueo,aiueo,aiueo
3,test1,test2,test3
$
$ awk -F, '{print $NF}'
ccc
aiueo
test3
$

フィールド数を取得できる”NF“と”$“で末尾の値を取得している。フィールド数がそれほどなければ末尾ひとつ前のフィールドの値もわかりやすいが、これ何番目だ?と数えるのが億劫な場合は下記で取得することができる。

$ awk -F, '{print $(NF-1)}' test.csv
bbb
aiueo
test2
$

以上。

paste

表題のコマンドについてメモ。知らなかった使い方だった。

■ 環境

  • Linux
  • Mac OSX El Capitan

■ paste

`paste`コマンドといえば、複数のファイルを行単位で結合するコマンドである。例えば下記のような実行結果となる。

$ cat test1
1
2
3
$ cat test2
a
b
c
$ paste test1 test2
1     a
2     b
3     c
$ cat test3
x
y
z
$ paste test1 test2 test3
1     a     x
2     b     y
3     c     z
$ paste -d , test1 test2 test3
1,a,x
2,b,y
3,c,z
$

今回はこれを応用(?)して、1つのファイルから行列(?)を作成する。元ファイルは下記のようなものである。

$ cat list
063
187
223
236
238
  :
$

これを2列に並べ替えるには下記のように実行する。

$ cat list | paste - -
063     187
223     236
238     239
  :
$

3列に並べ替えるのであれば下記のように実行する。

$ cat list | paste - - -
063     187     223
236     238     239
240     241     242
  :
$

“-“の数で列数を指定できる。CSVのようにするには下記である。

$ cat list | paste -d , - - -
063,187,223
236,238,239
240,241,242
  :
$

使い方によっては便利だ。

以上。

シェルスクリプトで終了処理

表題の通り。正常に最後まで終われば問題ないのだが、`kill`コマンドや”Ctrl-C“で終了させた時に決まった処理をさせたい。

■ 環境

  • sh

■ trap

ビルトインコマンドの`trap`を使う。例えば下記の通り。

#!/bin/sh

signals() {
  echo "exit"
  exit
}

trap signals SIGHUP SIGINT SIGKILL SIGTERM

echo "pid = $$"
while true
do
  /bin/echo -n "."
  sleep 3
done
echo "finish."

# EOF

`trap`の引数は下記の通りである。

trap 【処理 or 関数】 【シグナルの指定】

このスクリプトを実行する。

$ ./test.sh
pid = 17717
....

終了時に”signals()“を呼ぶようにしてみた。”exit“と出力して終了。

Ctrl-C“で終了すると下記のようになる。

$ ./test.sh
pid = 17717
.................................^Cexit
$

続いて別のターミナルから`kill`コマンドで停止してみる。

$ ./test.sh
pid = 17792
........exit
$

以上。

Macでの`echo -n`

表題の通り。忘れないようにメモ。

■ 環境

  • Mac OSX El Capitan

■ 改行無しの`echo`

文末の改行コードを無しにするオプションをたまに使うが、普段Linuxでの作業が多い為、Macで同じスクリプトを実行すると下記のようになってしまう。

$ ./test.sh
pid = 14810
-n .
-n .

単に”.“を表示していきたいだけだったのだが、”-n“オプション自体を`echo`で表示してしまっているようだ。

Macにおいては`echo`ではなく、`/bin/echo`で指定をしてあげなければならない。

まだ新人であった頃、shの師匠に言われた気がする。コマンドを使うときは絶対パスで指定しておいた方が良いと。確かに師匠が書いたスクリプトは基本的に絶対パスで書かれていたと記憶している。

以上。

curlコマンドのサイレントモード

表題の通り。先日のエントリで既にやっているが特に触れていなかったのでメモしておく。

■ 環境

  • curl
  • Mac OSX El Capitan

■ curl

`curl`のversionは下記の通り。

$ curl --version
curl 7.43.0 (x86_64-apple-darwin15.0) libcurl/7.43.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz UnixSockets
$

■ silent mode

shellスクリプトや最近であればDockerfileの中でなど、`curl`でファイルを取得するときに進捗状況(progress meter)が出力するのを制限することができる。

$ curl -s URL

もしくは

$ curl --silent URL

先日のエントリの実行結果をサイレントモードの有無でやってみる。

$ curl https://registry.hub.docker.com/v1/repositories/withsin/zookeeper/tags | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   128    0   128    0     0     33      0 --:--:--  0:00:03 --:--:--    33
[
  {
    "layer": "3db34bba",
    "name": "latest"
  },
  {
    "layer": "9cbde483",
    "name": "3.4.8"
  },
  {
    "layer": "9b796aa3",
    "name": "3.4.8-alpine"
  }
]
$
$ curl -s https://registry.hub.docker.com/v1/repositories/withsin/zookeeper/tags | jq .
[
  {
    "layer": "3db34bba",
    "name": "latest"
  },
  {
    "layer": "9cbde483",
    "name": "3.4.8"
  },
  {
    "layer": "9b796aa3",
    "name": "3.4.8-alpine"
  }
]
$

コマンドをターミナルで実行している場合には進捗状況が分かるのは良いのだが、スクリプト等では不要だろう。

以上。

■ 関連