Last active
March 13, 2016 09:13
-
-
Save papiron/f256f09e5a6ddde1d28f to your computer and use it in GitHub Desktop.
シェルスクリプト入門福岡の解答例
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2016/03/11 (金) に開催された「シェルスクリプト入門 福岡」の別解です。 | |
https://atnd.org/events/75045 | |
問題とデータは下記を参照のこと | |
https://github.com/ShuyaMotouchi/shellstadyQ | |
Tukubaiコマンドは下記を参照のこと。 | |
https://uec.usp-lab.com/TUKUBAI/CGI/TUKUBAI.CGI?POMPA=LIST | |
これらの解き方はあくまでも例に過ぎません。他にも色々なやり方があるので考えてみよう。 | |
解答例はMacを利用。GNU版のdateやsedは、gdateとgsedになっているので注意。 | |
Linuxの人はgdateとgsedをdateとsedで読み替えてください。 | |
この解答例は、USP友の会主催のシェル芸勉強会で培ったノウハウによるものです。 | |
https://www.usptomo.com | |
Q01 | |
test.txtの文字数を数えてください!!!出来る人はより変態に数えてください!! | |
$ cat test.txt | tr -d ' \n' | wc -m | |
10039 | |
$ cat test.txt | tr -d ' \n' | grep -o . | wc -l | |
10039 | |
$ cat test.txt | tr -d ' \n' | awk '{print length($0)}' | |
10039 | |
$ cat test.txt | tr -d ' ' | awk '{print length($0)}' | awk '{sum+=$0}END{print sum}' | |
10039 | |
$ cat test.txt | tr -d ' ' | sed 's/./& /g' | awk '{print NF}' | awk '{sum+=$1}END{print sum}' | |
10039 | |
numsumはbrew install num-utilsでインストール(Perlスクリプト群) | |
$ cat test.txt | tr -d ' ' | awk '{print length($0)}' | numsum | |
10039 | |
$ cat test.txt | tr -d ' ' | sed 's/./& /g' | awk '{print NF}' | numsum | |
10039 | |
Tukubaiコマンド利用 | |
$ cat test.txt | tr -d ' ' | sed 's/./& /g' | awk '{print NF}' | sm2 0 0 1 1 | |
10039 | |
以下は全てマルチバイト文字の場合限定(1文字3バイトの前提) | |
xxdコマンドはvimに付属のバイナリダンプコマンド。 | |
環境変数LANGがja_JP.UTF-8の必要有。 | |
$ cat test.txt | tr -d ' \n' | xxd -p | tr -d '\n' | gsed 's/....../&\n/g' | wc -l | |
10039 | |
$ cat test.txt | tr -d ' \n' | xxd -p | tr -d '\n' | grep -o ...... | wc -l | |
10039 | |
Q02 | |
シェルプログラミング実用テクニックは8章構成になっており | |
文章をまとめるために章毎にディレクトリーを作りたいが面倒なのでワンライナーで完成させたい!!! | |
この8つのディレクトリさえあれば良い!! | |
シェルプログラミング実用テクニック01章 | |
シェルプログラミング実用テクニック02章 | |
シェルプログラミング実用テクニック03章 | |
シェルプログラミング実用テクニック04章 | |
シェルプログラミング実用テクニック05章 | |
シェルプログラミング実用テクニック06章 | |
シェルプログラミング実用テクニック07章 | |
シェルプログラミング実用テクニック08章 | |
【bash ver4のみ】 | |
$ mkdir シェルプログラミング実用テクニック{01..08}章 | |
$ for n in {01..08}; do echo "シェルプログラミング実用テクニック"$n"章";done | |
seqコマンドで数字を列挙してから | |
$ seq 1 8 | sed 's/^/0/' | while read n; do mkdir "シェルプログラミング実用テクニック"$n"章"; done | |
$ seq 1 8 | awk '{printf "シェルプログラミング実用テクニック%02d章\n",$0}' | xargs mkdir | |
$ seq -f '%02.0f' 8 | sed 's/.*/シェルプログラミング実用テクニック&章/' | xargs mkdir | |
$ seq 1 8 | xargs printf "シェルプログラミング実用テクニック%02d章\n" | xargs mkdir | |
Q03 | |
test.txtの中からメロスという単語の数を数えてくれ!!! | |
$ cat test.txt | grep -o メロス | wc -l | |
76 | |
Q04 | |
test.txtのメロスを全員「もとうち」に名前に変換して出力せよ!!! | |
×出来る方は現在、ログインしているユーザーの名前に変えて出力して下さい!! | |
$ cat test.txt | sed "s/メロス/もとうち/g" | |
$ cat test.txt | sed "s/メロス/`whoami`/g" | |
$ cat test.txt | sed "s/メロス/$(whoami)/g" | |
Q05 | |
/home 以下から現在、ログインしているユーザーの名前を含むファイルを全て列挙して下さい。 | |
×少し難しい(シェル芸やってないと考え方が)ので飛ばしてもどうぞ!! | |
ログインユーザ名の文字列が含まれるファイルの列挙ということかな? | |
$ grep -rl `whoami` /home | |
Macな人だと/Users以下とかの方がいいかも | |
$ grep -rl `whoami` /Users | |
/Users/tashiro/.android/adbkey.pub | |
/Users/tashiro/.atom/.apm/.apmrc | |
/Users/tashiro/.atom/compile-cache/coffee/f55c001218bab56807639b76ab1aba348a7517f1.js | |
/Users/tashiro/.atom/storage/application.json | |
/Users/tashiro/.atom/storage/editor-0bb16aea324920774233b8b42594d0cd4d1c7eae | |
/Users/tashiro/.atom/storage/editor-31f79d0cadf44600c8dba38a4508c739eb712b32 | |
/Users/tashiro/.atom/storage/editor-ac1dd619274fc2e0887286782fb728005176bbd7 | |
/Users/tashiro/.atom/storage/editor-cb400d256f87a617231dd01de3606bbc1b982ab4 | |
/Users/tashiro/.atom/storage/editor-ccc56c1045bb938d76fcc3d5f2ac866daed5ff1e | |
/Users/tashiro/.bitclust/config | |
補足 | |
ファイル名とファイルの中身をセットで出力するならこんな感じ。 | |
$ grep -r '' /home | |
$ find /usr/home -type f | xargs awk '{print FILENAME,$0}' | |
Q06 | |
全ユーザーとホームディレクトリのみを列挙して下さい | |
hint:/etc/passwd | |
$ cat /etc/passwd | grep -o '^[^#]*' | sed '/^$/d' | awk -F: '{print $1,$(NF-1)}' | |
Tukubaiコマンド使用(self) | |
$ cat /etc/passwd | grep -o '^[^#]*' | sed '/^$/d' | tr ':' ' ' | self 1 NF-1 | |
Q07 | |
コマンド使用回数ランキングのトップ10を使用回数と一緒に | |
表示させよ。 | |
今回はls ls -a は別のコマンドとして扱う!! | |
historyから集計すればいい? | |
$ history | awk '{for(i=2;i<=NF;i++){printf "%s ",$i}print ""}' | sort | uniq -c | sort -k1,1nr | head | |
$ history | awk '{$1="";print}' | sort | uniq -c | sort -k1,1nr | head | |
Tukubaiコマンド使用(delf) | |
$ history | delf 1 | sort | uniq -c | sort -k1,1nr | head | |
Q08 | |
入門(普通の人) | |
プロセスのうちログインユーザが動かしているものだけを | |
出力して下さい | |
ps auxwwで全ユーザのプロセスを出したという前提で | |
$ ps auxww | awk '$1=="'$(whoami)'"{for(i=11;i<=NF;i++)printf "%s ",$i;print ""}' | |
Tukubaiコマンド使用(self) | |
$ ps auxww | awk '$1=="'$(whoami)'"' | self 11/NF | |
解けるもんなら解いてみろ!!!(変態用) | |
ログインユーザが動かしているプロセスのうち、メモリの使用率が | |
高いものから順番にPIDを10個出力してください | |
ps auxwwで全ユーザのプロセスを出したという前提 | |
$ ps auxww | awk '$1=="'$(whoami)'"' | sort -k4,4nr | head | awk '{for(i=11;i<=NF;i++)printf "%s ",$i;print ""}' | |
Tukubaiコマンド利用 | |
$ ps auxww | awk '$1=="'$(whoami)'"' | sort -k4,4nr | head | self 11/NF | |
Q09 | |
bashを使っているユーザーのログインシェルをbashからzshに変更する。 | |
実際には書き込まなくても良い!!! | |
というか書き込まないでくれ!!!! | |
こんな感じ?? | |
$ cat /etc/passwd | sed 's/bash$/zsh/' | |
Q10 | |
初心者のボス問題として作りました。 | |
問題はそんなに難しくないです。 | |
ワンライナーでtest.txtと似たような文章を出力して下さい。 | |
hint my blog | |
awk芸 | |
$ seq 20 | awk 'NR%2{print $0,"奇数"}NR%2==0{print $0,"偶数"}' | awk 'NR%5{printf $0" "}NR%5==0{print}' | |
$ seq 20 | awk 'NR%2{print $0,"奇数"}NR%2==0{print $0,"偶数"}' | xargs -n 10 | |
$ seq 1 20 | xargs -n 5 | awk '{for(i=1;i<=NF;i++)if($i%2==0){sub(/$/," 偶数",$i)}else{sub(/$/," 奇数",$i)};print}' | |
sed芸 | |
$ seq 20 | gsed '1~2s/$/ 奇数/' | gsed '0~2s/$/ 偶数/' | xargs -n 10 | |
補足 | |
xargsで並べかえする場合、データが多いと遅い。 | |
awkやTukubaiコマンドのyarrを使う方が高速。 | |
Q11 | |
2016年の日曜日を全て列挙してください。 | |
日付の場合はdateコマンドを使おう。GNU版とBSD版でオプションなどが異なる。 | |
とりあえずdateコマンドを366回実行する。(なので処理は遅い) | |
GNU dateの場合 | |
$ seq 0 365 | xargs -I@ gdate -d '20160101 @ day' '+%Y%m%d %a' | grep '日$' | |
BSD dateの場合 | |
$ seq 0 365 | xargs -I@ date -v+@d -j -f '%Y%m%d' 20160101 '+%Y%m%d %a' | grep '日$' | |
少し無駄をなくす。日曜日は7日毎なので下記のやり方でも良い | |
GNU dateの場合 | |
$ seq 2 7 365 | xargs -I@ gdate -d '20160101 @ day' '+%Y%m%d %a' | |
BSD dateの場合 | |
$ seq 2 7 365 | xargs -I@ date -v+@d -j -f '%Y%m%d' 20160101 '+%Y%m%d %a' | |
GNU dateコマンドで荒っぽい解き方。 | |
日付もどきの一覧を標準入力から食わせる。不正な日付はエラー出力されるので捨て去る。 | |
dateコマンドは一回だけ実行なので処理は速い。 | |
$ seq -w 0101 1231 | sed 's/^/2016/' | gdate -f - "+%Y%m%d %a" 2> /dev/null | grep '日$' | |
Tukubaiのmdateコマンドなどを使うと、高速で簡潔に処理が出来る。 | |
$ mdate -e 20160101 20161231 | tarr | yobi -j 1 | grep '日$' | |
Q12 | |
fizzBuzz | |
オーソドックスな解答 | |
$ seq 1 20 | awk '$1%3==0{printf "Fizz"}$1%5==0{printf "Buzz"}{print " " $1}' | awk '{print $1}' | |
ちょっと頭おかしいsed芸 | |
$ seq 1 20 | gsed '5~5s/.*/Buzz/' | gsed '3~3s/[0-9]*/Fizz/' (GNU sedのみ) | |
$ seq 1 20 | sed 'n;n;s/.*/Fizz/' | sed 'n;n;n;n;s/[0-9]*$/Buzz/' | |
$ seq 1 20 | sed 'n;n;s/.*/Fizz/' | sed 'n;n;n;n;/F/s/$/Buzz/;/F/!s/.*/Buzz/' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment