labunix's blog

labunixのラボUnix

USP友の会 20130622第5回シェル芸勉強を解いてみた。

■USP友の会 201306225回シェル芸勉強を解いてみた。

 201306225回シェル芸勉強会スライド
 http://www.slideshare.net/ryuichiueda/20130622-23348634

問題1
 ・あるディレクトリで適当にファイルへのシンボリックリンクを作り、
  リンク先のファイルをコピーして実体のあるファイルに置き換えてください。

■シンボリックは「-h」で判定、「cp -b」でバックアップオプションを指定。

$ ln -s /var/log/syslog syslog; \
  ln -s /var/log/syslog.1 syslog.1
$ ls -l | sed s/`whoami`/"sample"/g
合計 0
lrwxrwxrwx 1 sample sample 15 1014 21:42 syslog -> /var/log/syslog
lrwxrwxrwx 1 sample sample 17 1014 21:42 syslog.1 -> /var/log/syslog.1

$ for list in *;do test -h "$list" && sudo cp -b `readlink -f $list` $list;done
$ ls -l | sed s/"`whoami`\|root"/"sample"/g
合計 288
-rw-r----- 1 sample    sample     15182 1014 21:50 syslog
-rw-r----- 1 sample    sample    274641 1014 21:50 syslog.1
lrwxrwxrwx 1 sample sample     17 1014 21:49 syslog.1~ -> /var/log/syslog.1
lrwxrwxrwx 1 sample sample     15 1014 21:49 syslog~ -> /var/log/syslog

問題2
 ・/etc/hostsと/etc/resolv.confをつなげて、以下のように各行に元のファイル名が
  ついた一つのファイルを作ってください。

/etc/hosts ##
/etc/hosts # Host Database
/etc/hosts #
()
/etc/resolv.conf #
/etc/resolv.conf # Mac OS X Notice
/etc/resolv.conf #
()


■サンプルから。

$ grep . switchconf/examples/home/etc/{hosts,resolv.conf} | \
  sed s%"switchconf/examples/home"%%g | tr ':' ' '
/etc/hosts 127.0.0.1	localhost
/etc/hosts 192.168.0.16	myhost.myhome.org	myhost
/etc/resolv.conf search myhome.org 
/etc/resolv.conf nameserver 192.168.0.254

問題3
 ・問題2で作ったファイルを適当なディレクトリの下に復元してください。

■ノーマルに。

$ for list in hosts resolv.conf;do \
    COUNT=`echo "/etc/$list " | wc -c` ; \
    grep "$list" sample | cut -c ${COUNT}- >> "$list"; \
  done
$ grep . hosts resolv.conf | tr ':' ' '
hosts 127.0.0.1	localhost
hosts 192.168.0.16	myhost.myhome.org	myhost
resolv.conf search myhome.org 
resolv.conf nameserver 192.168.0.254

問題4
 ・a,bそれぞれについて一番下にある行を取り出してください。

$ cat data2 
a 14
a 5
b 12
b 3
a 20
b 1
b 22種類しかないので。

$ awk '{if($1=="a"){a=$0}else{b=$0}};END{print a"\n"b}' data2 
a 20
b 2

問題5
 ・下の図のように魔方陣を作って、
  魔方陣になっているかどうか確認してください。

■縦横の合計すべてが等しい数の行列の計ならOK。

$ echo $(sed s/" "/"+"/g data1 | bc;awk '{a+=$1;b+=$2;c+=$3};END{print a,b,c}' data1) | \
  sed s/" "/"\n"/g | uniq -c | awk '($1==6){print "魔方陣"}'
魔方陣

問題6
 ・/usr/share/dict/words 等辞書から大文字で始まる単語、
  小文字で始まる単語の数を数えてください。

■セミコロンで区切っても区切らなくても。

$ echo -n "小文字で始まる単語の数:";grep ^[a-z] /usr/share/dict/words | wc -l; \
  echo -n "大文字で始まる単語の数:";grep ^[A-Z] /usr/share/dict/words | wc -l;
小文字で始まる単語の数:82671
大文字で始まる単語の数:16483

$ echo `grep ^[a-z] /usr/share/dict/words | wc -l` `grep ^[A-Z] /usr/share/dict/words | wc -l`
82671 16483

問題7

$ echo ダァシェリイェス
して、ワンライナーで時を斑点してください。
(「ダ」がめんどくさい)

■nkf使ってもいいし、使わなくてもいい。

$ echo ダァシェリイェス | nkf | sed s/./"&\n"/g | tac | xargs echo -n | tr -d ' ' | nkf -Z4;echo
スェイリェシァダ
$ echo ダァシェリイェス | sed s/"ダ"/""/ | sed s/./"&\n"/g | tac | xargs echo -n | tr -d ' ' | sed s/""/"ダ"/;echo 
スェイリェシァダ

問題8
 ・以下のような図形を出力してください。
    a
   aaa
  aaaaa
 aaaaaaa
  aaaaa
   aaa
    a


■わかりやすく。

$ echo $(echo "<div align=center>"; \
  for n in 1 3 5 7 5 3 1;do \
    echo `seq 1 $n` | sed s/[0-9]/a/g | tr -d ' ';echo "<br/>"; \
  done;echo "</div>")  | \
  w3m -dump -T text/html -cols 10
    a
   aaa
  aaaaa
 aaaaaaa
  aaaaa
   aaa
    a

問題9
 ・右図のように縦に1つずつランダムにずらして字を出力してください。

$ echo 15 | awk '{a=10;for(i=1;i<=$1;i++){a=a+(rand()>0.5?-1:1);print a}}' | \
  awk '{for(i=1;i<=$1;i++){printf " "}{printf "o\n"}}'
           o
            o
           o
            o
           o
            o
           o
            o
             o
              o
               o
                o
               o
                o
               o

■右か左かに限定した場合

$ seq 0 9 | sort -R | \
  for n in `xargs`;do echo $n | awk '{if($n%2==0){print " o"}else{print "o "}}';done
 o
o 
 o
o 
o 
 o
 o
o 
 o
o 

■「%3」だとひとつ飛びになることがある。

$ seq 0 11 | sort -R | \
  awk '{print $1%2}' | \
  for n in `xargs`;do \
    for m in `seq 0 11`;do \
      if [ $m -eq $(($n+10)) ];then echo "o";break;else echo -n " ";fi; \
    done; \
  done
           o
           o
          o
           o
          o
          o
           o
          o
           o
          o
          o
           o


問題10
 ・/usr/share/dict/words から中手流した単語で、

  this is a pen

  という出力を得てください。
  ーただし、数字は一切使わないこと
  ーシェル変数、ファイルにも出力しないこと
  ーfor,while,&&禁止

■数字を使う方法

$ grep "^this\$\|^is\$\|^a\$" /usr/share/dict/words | xargs echo -n | \
   sed s/"\(.\) \(..\) \(...\) \(....\)"/"\4 \2 \1 \3"/;echo
this is a pen

■解答例をヒントに強引に順番を作る方法

$ sed s/"^this\$"/"_&"/ /uwords | sed s/"^is\$"/"__&"/ | \
  sed s/"^a\$"/"___&"/ | sed s/"^pen\$"/"____&"/ | \
  grep "^_" | sort -r | tr -d "_" | tr '\n' ' ';echo
this is a pen