■USP友の会 20131102 第7回シェル芸勉強会 を解いてみた。 今回を除くと、8,9回の2回分ですか。。。 シェル芸勉強会スライド一覧 http://blog.ueda.asia/?page_id=684 USP友の会 20130622第5回シェル芸勉強を解いてみた。 http://labunix.hateblo.jp/entry/20141014/1413298748 USP友の会 勉強会 番外編(OSC 2013 Tokyo/Spring)を解いてみた。 http://labunix.hateblo.jp/entry/20141013/1413129899 「第13回危険でない方のシェル芸勉強会」を解いてみた。 http://labunix.hateblo.jp/entry/20141005/1412439761 ■それでは。 問題1 ・ドットで区切られた4つの数字について、 左側の数字を優先に 数字の小さい順に並べてください。 $ cat ip 123.45.6.78 1.9.8.4 1.119.8.4 199.9.31.123 20.123.123.123 19.345.6.78 ■これはノーマルに。 $ sort -t\. -n -k 1,1 -k 2,2 -k 3,3 -k 4,4 ip 1.9.8.4 1.119.8.4 19.345.6.78 20.123.123.123 123.45.6.78 199.9.31.123 問題2 ・次の文について、tax,1km,10000の前後に半角スペースを挿入してください。 このtaxiは1kmあたり10000円 ■なんとなく「&」を使わない方法で。 $ echo "このtaxiは1kmあたり10000円" | \ sed s/"\([a-z0-9][a-z0-9]*\)"/" \1 "/g この taxi は 1km あたり 10000 円 問題3 ・次の文についてspaceの前・invaderの後ろ・ 4の後ろのスペースを除去してください。 私の名前は space invader です。4 歳です。 ■後から楽に読めるように。 $ echo "私の名前は space invader です。4 歳です。" | \ sed s/" \(space invader\) \(です。4\) "/"\1\2"/ 私の名前はspace invaderです。4歳です。 問題4 ・次のマーク付きの文について 「<b>hoge</b>」が重複していることをワンライナーで示してください。 <b>hoge</b>は<b>fuga</b>なので<b>hoge</b>fugaだよね。 ■普通に解く。 $ echo '<b>hoge</b>は<b>fuga</b>なので<b>hoge</b>fugaだよね。' | \ sed s%"/b>"%"&\n"%g | sed s/"<b"/"\n&"/g| grep "<" | \ sort | uniq -c | awk '($1>1){print $2}' <b>hoge</b> 問題5 ・00001~20000という名前の空のファイルを作ってください。 ■この位は日常。 $ touch `seq -w 1 20000` $ ls 0000* 2000* 00001 00002 00003 00004 00005 00006 00007 00008 00009 20000 $ ls [012]* | wc -l 20000 問題6 ・a)さきほど作った2万個のファイルのリストをなるべき短い時間で作ってください。 ・b)ファイルを消してください。 ■多分意図と異なるがソートしないlsより、echoの方が速い。 ただし、正順だが区切りは空白。 $ time echo * >/dev/null real 0m0.086s user 0m0.072s sys 0m0.016s $ time ls -f * >/dev/null real 0m0.116s user 0m0.072s sys 0m0.044s $ time echo * | xargs rm -f real 0m0.274s user 0m0.088s sys 0m0.188s 問題7 ・右下の図のようなディレクトリ、ファイルを作り、 例えば、 ./a/001なら./a_001 ./b/c/123なら./b_c_123 のようにパスの「/」をアンダースコアに変えて、 「./」にコピーを置いてください。 -できる人はwhileやforを使わないで ■とりあえず作るところから。 $ mkdir -p a b/c;touch a/{001,002} b/c/123 b/{xxx,yyy} $ tree . ├── a │ ├── 001 │ └── 002 └── b ├── c │ └── 123 ├── xxx └── yyy 3 directories, 5 files ■まあ、2回位なら。 $ find . -type f | cut -c 3- | awk '{print "cp "$0,$0";"}' | \ sed s%"/\([a-z0-9]*;\)"%"_\1"% | sed s%"/\([a-z0-9_]*;\)"%"_\1"% | sh $ find . -type f | grep _ ./b_yyy ./a_001 ./a_002 ./b_xxx ./b_c_123 問題8 ・/etc/ 下の読み込み可能な書くファイルについて、 fooと書いてある行の行数を数えてください。 ■あれ、書くファイルの行数じゃ。。。 $ grep -r -a foo /etc/ 2>/dev/null | awk -F\: '{print $1}' | uniq -c | \ sed s%"\( /etc/\).*"%"\1hoge"% | awk '{sum+=$1;print};END{print sum}' 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 5 /etc/hoge 2 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 4 /etc/hoge 1 /etc/hoge 4 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 3 /etc/hoge 3 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 14 /etc/hoge 1 /etc/hoge 10 /etc/hoge 11 /etc/hoge 1 /etc/hoge 1 /etc/hoge 21 /etc/hoge 1 /etc/hoge 2 /etc/hoge 12 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 17 /etc/hoge 6 /etc/hoge 12 /etc/hoge 1 /etc/hoge 21 /etc/hoge 5 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 3 /etc/hoge 1 /etc/hoge 1 /etc/hoge 194 問題9 ・今度は、/etc/ 下の読み込み可能な各ファイルについてfooの数を数えてください。 $ grep -r -a -o foo /etc/ 2>/dev/null | uniq -c | \ sed s%"\( /etc/\).*"%"\1hoge"% | awk '{sum+=$1;print};END{print sum}' 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 8 /etc/hoge 2 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 4 /etc/hoge 1 /etc/hoge 4 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 4 /etc/hoge 3 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 20 /etc/hoge 1 /etc/hoge 10 /etc/hoge 14 /etc/hoge 1 /etc/hoge 1 /etc/hoge 29 /etc/hoge 1 /etc/hoge 4 /etc/hoge 14 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 2 /etc/hoge 23 /etc/hoge 6 /etc/hoge 15 /etc/hoge 1 /etc/hoge 29 /etc/hoge 7 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 1 /etc/hoge 3 /etc/hoge 2 /etc/hoge 2 /etc/hoge 240 問題10 ・日付の古い順にソートしてください。 $ cat days Jan 4, 2012 Jul 19, 2013 Jul 2, 2013 Apr 9, 2010 Oct 30, 2012 ■manマニュアル通りではなく、大文字小文字混在でも通るらしい。 $ man sort 2>/dev/null | grep 月名 月名でソートする。(不明) < 'JAN' < ... < 'DEC' の順 $ cat days | tr '[a-z]' '[A-Z]'| sort -k 3,3 -k1,1M -k 2,2n | \ sed 's/^\([A-Z]\)\(.*\)/\1\L\2/' Apr 9, 2010 Jan 4, 2012 Oct 30, 2012 Jul 2, 2013 Jul 19, 2013 $ sort -k 3,3 -k1,1M -k 2,2n days Apr 9, 2010 Jan 4, 2012 Oct 30, 2012 Jul 2, 2013 Jul 19, 2013