hbstudy#38シェルスクリプト(Open usp Tukubai)で
いろいろやってみよう!
USP研究所/USP友の会 上田 隆一
2012年10月27日 hbstudy#38 2
自己紹介&近況● 自己紹介
– 赤いパーカーのおじさん
– USP研究所スーパー平社員にしてUSP友の会の会長
● 近況– 連載が好評らしいです。
● Software Design 誌 「お彼岸開眼シェルスクリプト」
– TechLION vol. 10 来てね● 村井先生● 11/16(金)の夜@六本木
2012年10月27日 hbstudy#38 3
今日やること
何したらおもしろい&ためになるかこの一ヶ月間悩みました。
2012年10月27日 hbstudy#38 4
今日やること
● Open usp Tukubai の紹介をしようにも、何に使うか分からなければつまらん– 道具だけ話してもね・・・
– バットの使い方の説明をして野球をしないようなもの
2012年10月27日 hbstudy#38 5
今日やること
● 「GUIに慣れてしまった現代人に足りないのはシェル芸だ!」
→ シェル芸人育成ドリルをやります
● (ついでにopen usp tukubaiもやる。便利だから)
2012年10月27日 hbstudy#38 6
シェル芸とは?
● こんなことはないですか?– よくある風景A
● 上司S: 「ん?このマシンなんか設定おかしくない?」● 部下M: (hogehoge.confをlessして・・・)
「うわー、この設定ファイル100万行あるから、あと5時間くらい待ってください。」
– よくある風景B● 上司S:「このディレクトリに100万個ファイルがある。
このうちファイル名にaの付くものだけをこっちのディレクトリに移しなさいっ。」
● 部下M:「はい!マウスで・・・」
2012年10月27日 hbstudy#38 7
シェル芸とは?
● マウスも使わず、プログラムも書かず、GUIツールを立ち上げる間もなく、あらゆる調査・計算・ファイル処理をコマンド入力一撃で終わらす。
※シェル芸人イメージ(麻雀は天和で終わらす)
2012年10月27日 hbstudy#38 8
ということで
● 端末操作だけでいろんな仕事をできるようになってもらいます。
– シェルスクリプトなぞ大規模エンタープライス用
– 今回の内容をおさえればクソ長いシェルスクリプトは書かなくなることでしょう・・・
– 今回はエディタすら使用禁止
2012年10月27日 hbstudy#38 9
時間割
● 前半戦(~19:30)– 普通のコマンドで端末と格闘
– 桜井章一氏等の言うところの「ヒラッコ」
● 休憩と準備(19:30~19:50)– open usp Tukubai インストール
● 後半戦(~21:20)– open usp Tukubaiも使って端末と格闘
– 桜井章一氏等の言うところの「裏技」
2012年10月27日 hbstudy#38 10
進め方(どうせバイニン玄人が潜んでいるので・・・)
● カップリングペアリングします。
● ペア(3人グループも可)作ってください– UNIX系OSでCUI歴が長い人 × そうでもない人
● とにかくみんなで問題を解いていきます。– なるべく多くの人が解けるまで待ちます。
– 問題がすぐ解けてしまったら、部屋を回って他の方の指導をお願いします。
2012年10月27日 hbstudy#38 11
問題の解き方
● 基本はbashかshで
● 使えるコマンドはなんでも使え– posixとか気にするのはできるようになってから!
● できる人はいろいろな方法で挑戦– それも終わったら他の人を指導
– 玄人勢の献身がこの勉強会を成功させます!
2012年10月27日 hbstudy#38 12
問題1: ユーザの抽出(初級)
● /etc/passwd から、ユーザ名を抽出したリストを作ってください– 使いそうなコマンド:
awk, sed, tr, cut, ...
2012年10月27日 hbstudy#38 13
問題1: 答え
● $ awk -F: '{print $1}' /etc/passwd > ans.1
● $ sed 's/:..*//' /etc/passwd > ans.2
● $ cut -d: -f1 /etc/passwd > ans.3
● $ tr ':' ' ' < /etc/passwd | awk '{print $1}' > ans.4
● $ awk '{sub(/:..*/,"",$0);print}' /etc/passwd > ans.5
● $ perl -F: -lane 'print $F[0]' /etc/passwd > ans.6
● $ ruby -F: -ne 'puts $_.split[0]' /etc/passwd > ans.7
2012年10月27日 hbstudy#38 14
問題2: ユーザの抽出2(中級)
● /etc/passwd から、次を調べてください。– ログインシェルがbashのユーザとshのユーザ、どちらが多い?
● cut, awk, sort, uniq, grep, ...
一目見て分かれば出力はなんでもよいです。
2012年10月27日 hbstudy#38 15
答え
● $ cut -d: -f7 /etc/passwd | grep -E '/(ba)?sh$' | sort | uniq -c > ans.1
● $ sed 's;^..*/;;' /etc/passwd | awk '/^bash$|^sh$/' | sort | uniq -c > ans.2
● $ awk -F/ '$NF=="sh"||$NF=="bash"{print $NF}' /etc/passwd | sort | uniq -c > ans.3
● $ awk -F/ '{print $NF}' /etc/passwd | awk '/^sh$|^bash$/' | sort | uniq -c > ans.4
2012年10月27日 hbstudy#38 16
問題3: ファイルの一括変換(中級)
● /etcの下にあるすべてのbashスクリプト(#!/bin/bashで始まるもの)について以下の操作をしてください。– ~/hogeというディレクトリにコピー
– その際、 「#!/bin/bash」を「#!/usr/local/bin/bash」 に変更
– grep, sed, ...
2012年10月27日 hbstudy#38 17
答え
● $ grep -r '#!/bin/bash' /etc 2> /dev/null | sed 's/:..*$//' | while read f ; do sed 's;#!/bin/bash;#!/usr/local/bin/bash;' $f > ~/hoge/$(basename $f) ; done
2012年10月27日 hbstudy#38 18
問題4: 集計(中級)
● 左のようなファイルを作り、右のように集計してください。
–
– awk, sort, sed, uniq, ...
2012年10月27日 hbstudy#38 19
答え● $ awk '{print int($1/10)}' ages | sort -n | uniq -c |
awk '{print $2*10"~"$2*10+9,$1}' > ans.1
● $ sed 's/.$//' ages | sed 's/^$/0/' | sort -n | uniq -c | awk '{print $2*10"~"$2*10+9,$1}' > ans.2
● $ cat ages | sed 's/.$//' | sed 's/^$/0/' | sort -n | uniq -c | awk '{print $2*10,$2*10+9,$1}' | sed 's/ /~/' > ans.3
2012年10月27日 hbstudy#38 20
問題5: Fizz Buzz (上級)
● 1,2,3,4,5...と数えていって・・・
– 3の倍数だったら数字の代わりに「Fizz」
– 5の倍数だったら数字の代わりに「Buzz」
– 15の倍数だったら数字の代わりに「FizzBuzz」
と言う。● 出力:
– 1,2,Fizz,4,Buzz,...,11,Fizz,13,14,FizzBuzz,16,...
– awk, sed, ...
2012年10月27日 hbstudy#38 21
答え● 素直にif文を書く
– $ seq 1 100 | awk '{if($1%15==0){print "FizzBuzz"}else if($1%5==0){print "Buzz"}else if($1%3==0){print "Fizz"}else{print $1}}' | tr '\n' ','
● 先に計算を済ませる
– $ seq 1 100 | awk '{print $1,$1%3,$1%5,$1%15}' | awk '{a=$1;if($4==0){a="FizzBuzz"}else if($3==0){a="Buzz"}else if($2==0){a="Fizz"};print a}' | tr '\n' ','
● 意地でもif文を使わない
– $ seq 1 16 | awk '$1%3==0{printf "Fizz"}$1%5==0{printf "Buzz"}{print " " $1}' | awk '{print $1}' | tr '\n' ','
2012年10月27日 hbstudy#38 22
● sedる
– $ seq 1 16 | awk '{print $1,$1%3,$1%5}' | sed 's/..* 0 0$/FizzBuzz/' | sed 's/..* 0$/Buzz/' | sed 's/..* 0 ..*$/Fizz/' | awk '{print $1}' | tr '\n' ','
● 三項演算子る
– $ seq 1 16 | awk '{print $1%15==0?"FizzBuzz":$1%5==0?"Buzz":$1%3==0?"Fizz":$1}' | tr '\n' ','
– $ seq 1 16 | awk '{printf $1%15==0?"FizzBuzz":$1%5==0?"Buzz":$1%3==0?"Fizz":$1; printf ","}'
2012年10月27日 hbstudy#38 23
休憩前に● Open usp Tukubai のインストールをお願いします。● ダウンロード方法
– $ wget --no-check-certificate https://uec.usp-lab.com/TUKUBAI/DOWNLOAD/open-usp-tukubai-20120802.tar.bz2
● インストール方法– $ tar xjvf ./open-usp-tukubai-20120802.tar.bz2
– (rootになって、open-usp-tukubai-20120802に移動)
– # make install
● 端末で join0 と打って、usageが出てきたらインストール完了
2012年10月27日 hbstudy#38 24
後半戦
● open usp Tukubai の得意な処理
2012年10月27日 hbstudy#38 25
問題6: 日付の計算 (中級)
● 1978年2月16日は、2012年10月27日の何日前でしょう?– echo, date, tr, awk, ...
– mdate (オンラインマニュアル参照のこと)
2012年10月27日 hbstudy#38 26
答え
● Tukubai 未使用– $ echo 19780216 20121027 | tr ' ' '\n' | date +%s -f - | tr '\n' ' ' | awk '{print $1-$2}' | awk '{print $1/(24*60*60)}'
-12672
● Tukubai 使用– $ mdate 19780216 20121027
-12672
ということで12672日前でした。
2012年10月27日 hbstudy#38 27
問題7: リストにないものを探す(中級)
● まず以下のように、1から10の数字が書いてあり、そのうちの一つの数が欠けているファイルを作りましょう。
● 欠けた数字を端末に表示してください。(diff, 目grep禁止)
– sort, uniq, awk, join0,...
2012年10月27日 hbstudy#38 28
答え
● Tukubaiなし– $ seq 1 10 | sort - nums | uniq -u
– $ sort nums <(seq 1 10) | uniq -u (邪道)
– $ cat nums | awk '{a+=$1}END{print 55-a}'
● Tukubai的正攻法– $ seq 1 10 | sort > tran
– $ sort nums | join0 +ng key=1 - tran > /dev/null
2012年10月27日 hbstudy#38 29
問題8: CPU使用率(上級)
● topの出力から、どのユーザが何%CPUを使用しているか集計してください。
● top 出力のファイルへの渡し方– $ top -b -n 1 | command ...
– tail, awk, sort, sm2, self, ...
– ※psから計算したほうがよかったと、後から気づく
2012年10月27日 hbstudy#38 30
答え● Tukubai なし
– $ top -b -n 1 | tail -n +8 | awk '{print $2,$9}' | sort | awk '{if($1==u){c+=$2}else{print u,c;u=$1;c=$2}}END{print u,c}' | sort -k2,2nr
● Tukubai あり– $ top -b -n 1 | awk 'NF==10' | tail -n +2 | self 2 9 |
sort | sm2 1 1 2 2 | sort -k2,2nr
(Tukubaiを覚えないと、端末で済ませる発想にならないかも・・・)
※連想配列を使うともっと簡単です。
2012年10月27日 hbstudy#38 31
問題9: 横に並んだ数字のソート(上級)
● 次のように、適当に数字が記入されたファイルを作ってください。
● 各行ごとに、数字を小さい順にソートしてください。– awk, sort, tr, juni, tarr, yarr, delf, ...
2012年10月27日 hbstudy#38 32
答え
● Tukubai なし– $ cat -n file | awk '{for(i=2;i<=NF;i++){print $1,$i}}' | sort -k1,1n -k2,2n | awk '{if($1!=a){a=$1;printf "n"};print $2}' | tr '\n' ' ' | tr 'n' '\n' | awk 'NF!=0'
● Tukubai あり– $ juni file | tarr num=1 | sort -k1,1n -k2,2n | yarr
num=1 | delf 1
2012年10月27日 hbstudy#38 33
問題10: 対戦表を作る(上級)
● 左のようなファイルを作って、右のようなcsv形式の表を作ってください。
– tac, awk, sed, tr, loopx, map, ...
2012年10月27日 hbstudy#38 34
答え
● Tukubai なし– $ cat teams | awk '{a=a " "$1;print $1}END{print
a}' | tac | awk 'NR==1{print "_",$0;num=NF}{printf $1;for(i=1;i<=num;i++){printf ","};print ""}' | sed 's/ */,/g' | tr -d '_' > ans.1
● Tukubai あり– $ loopx teams teams | awk '{print $0,"_"}' | map
num=1 | tr ' ' ',' | tr -d '*_' > ans.2
2012年10月27日 hbstudy#38 35
まとめ
● お疲れさまでした!!● このままシェル芸人の道を邁進するには?
– manと格闘
– USP友の会入会入信