拡張 POSIX シェルスクリプト Advent Calendar 2013、22日目の記事です。
- 第8回クリスマスってなんだっけ シェル芸なら知っている勉強会 (問題だらけスライド)
なるべく POSIX sh で、無理なものは bash, ksh で解きました。 外部コマンドなし縛り。(md5sum は除く)
問題1 数字の並びを 2つずつフリップする
#!/bin/sh
echo 1 2 3 4 5 6 7 8 9 10 |
(
set -- `read l; echo $l`
r=''
while [ $1 ]; do r="$r $2 $1"; shift 2; done
echo $r
)
# 2 1 4 3 6 5 8 7 10 9
問題2 「ユニケージ」「ユニゲージ」「UPS」「USP」の各個数を数える
#!/bin/bash
echo ユニゲージユニケージユニゲージUSP友の会USP友の会 UPS友の会UPS友の会 |
(
read l
ns=
for k in ユニケージ ユニゲージ UPS USP; do
n=0
while :; do
x="${l/$k/}"
[[ $x = $l ]] && break
((n++))
l="$x"
done
ns="$ns $n"
done
echo $ns
)
# 1 2 2 2
問題3 4個のファイルを作り同じ内容のものを探し出すワンライナー
パス。あとでやる。
問題4 数字の列を偶数と奇数に分ける
sh 版。
#!/bin/sh
echo 3 8 2 10 1 8 9 |
(
read l
e=
o=
for n in $l; do
case $n in *[13579]) o="$o $n";; *) e="$e $n";; esac
done
echo $e $o
)
# 8 2 10 8 3 1 9
bash 版。
#!/bin/bash
echo 3 8 2 10 1 8 9 |
(
read l
e=
o=
for n in $l; do
((n%2)) && o="$o $n" || e="$e $n"
done
echo $e $o
)
# 8 2 10 8 3 1 9
問題5 ビット列の 0 と 1 の連続数を数える
#!/bin/sh
echo 000001111111111001010 |
(
read l
r=
[ "${l#0}" = "$l" ] && m=0 || m=1
while :; do
p=${l%%$m*}
[ -z "$p" ] && break
[ $m -eq 0 ] && m=1 || m=0
r="$r $m"
[ ${#p} -gt 1 ] && r="$r${#p}"
l=${l#$p}
done
echo $r
)
# 05 110 02 1 0 1 0
問題6 連続する数列をハイフンでまとめる
以前やったネタだけど、 出力形式が微妙に異なるので調整した。
#!/bin/bash
echo 1 2 3 5 6 8 10 11 12 15 |
(
read l
s=${l%% *}
((p=x=s-1))
for n in $l x; do
((n-p-1)) && {
((p-x)) && o=$o-$p
o="$o $n"
x=$n
}
p=$n
done
o=$s${o#-$s}
echo ${o% x}
)
# 1-3 5-6 8 10-12 15
問題7 数字3桁のパスワードの MD5 ハッシュ値から平文パスワードを求める
#!/bin/bash
echo 250cf8b51c773f3f8dc8b4be867a9a02 |
(
read l
n=0
while [[ $n -lt 1000 ]]; do
p=$(printf '%03d' $n)
h=$(echo -n $p |md5sum)
if [[ ${h%% *} = $l ]]; then
echo $p
break
fi
((n++))
done
)
# 456
問題8 /usr/share/dict/wordでしりとり
ksh で適当に実装。 「é」とか含まれているので bash だと動かない。
#!/bin/ksh
typeset -a words
typeset -l word_lower
for letter in {a..z}; do
eval typeset -a words_by_"$letter"
done
while read -r word; do
word_lower="$word"
words+=("$word")
letter="${word_lower:0:1}"
eval words_by_$letter+='($word)'
done </usr/share/dict/words
word="${words[$RANDOM % ${#words[@]}]}"
unset words
echo "$word"
while :; do
word_lower="$word"
letter="${word_lower:${#word}-1:1}"
eval words_by_letter_num='${#words_by_'"$letter"'[@]}'
[[ words_by_letter_num -eq 0 ]] && break
index=$(($RANDOM % $words_by_letter_num))
eval word='${words_by_'"$letter"'['"$index"']}'
eval unset 'words_by_'"$letter"'['"$index"']'
echo "$word"
done
ふつうにスクリプトになってしまった。何のひねりもない…。
ところで、12月25日はクリスマスな上に、
OSS 界隈で地味に活躍されているふみやすさんの誕生日ですね!
っ http://www.amazon.co.jp/registry/wishlist/27M7TV8CEEF6G?sort=priority
逆に、あなたの書いた OSS や Blog や Advent Calendar が気に入ったら何か送りたく なってしまうかもしれないので、プロフィールや Web サイトに あなたの Amazon 欲しいものリストの URL を貼っておいてくださいね!
私が勤める OSSTech っていう某弊社で社員募集しているようです。 人材紹介会社を介さなければ、入社後に 20万円のボーナス! 「ふみやすっていう人に紹介された」と言ってもらえると私にもボーナス!! → https://www.osstech.co.jp/recruit/
よろしければ、これまで参加した/参加予定のほかの Advent Calendar もどうぞ。
- Ansible Advent Calendar 2023
- シェル芸 Advent Calendar 2023
- 闇の魔術に対する防衛術 Advent Calendar 2023
- Ansible Advent Calendar 2023
- Ansible Advent Calendar 2020
- DNS温泉 Advent Calendar 2019
- OSSTech Advent Calendar 2019
- Ansible Advent Calendar 2018
- OSSTech Advent Calendar 2018
- Debian/Ubuntu Advent Calendar 2017
- Linux Advent Calendar 2017
- Shell Script Advent Calendar 2017
- Shell Script Advent Calendar 2016
- OpenLDAP と仲間たち Advent Calendar 2015
- Postfix Advent Calendar 2014
- 拡張 POSIX シェルスクリプト Advent Calendar 2013