はじめに
いろいろと思いつくままに書いてみました。実は paste コマンドのちょっとめずらしい(?)使い方の紹介です。
※ paste コマンドは他のコマンドに比べてあまり有名ではありませんが POSIX で規定されたコマンドです。
出力結果
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
seq
seq 9 | while read i; do
seq -f "$i*%0g" 9
done | while read a; do
eval 'echo $a=$(($a))'
done | paste - - - - - - - - -
備考 seq が POSIX 準拠ではない
ブレース展開
printf '%s\n' {1..9}"*"{1..9} | while read a; do
eval 'echo $a=$(($a))'
done | paste - - - - - - - - -
備考 ブレース展開が POSIX シェル準拠ではない
for
for i in 1 2 3 4 5 6 7 8 9; do
for j in 1 2 3 4 5 6 7 8 9; do
echo "$i*$j=$((i*j))"
done
done | paste - - - - - - - - -
備考 POSIX 準拠。9 個ぐらいならそのまま値を書いていいよね?
while
i=0
while [ "$i" -lt 9 ] && i=$((i+1)) j=0; do
while [ "$j" -lt 9 ] && j=$((j+1)); do
echo "$i*$j=$((i*j))"
done
done | paste - - - - - - - - -
備考 POSIX 準拠。無理やり詰め込んで行数を少なくしてみた
計算マニア
i=0
while [ "$i" -lt 81 ]; do
echo "$(( i/9+1 ))*$(( i%9+1 ))=$(( (i/9+1) * (i%9+1) ))"
i=$((i+1))
done | paste - - - - - - - - -
備考 POSIX 準拠。ここまでして二重ループを削除する必要はあるか?(ない)
bc
for i in 1 2 3 4 5 6 7 8 9; do
for j in 1 2 3 4 5 6 7 8 9; do
echo "\"$i*$j=\"; $i*$j"
done
done | bc | paste - - - - - - - - -
備考 Bourne シェルでも動く
expr を使ってもできますがループで毎回外部コマンドを呼び出すと遅くなるので、計算式を bc コマンドに与えることで高速化しています。(参考 シェルスクリプトのための良いデザイン ~ expr と bc から知る設計の違い ~)
paste 使わない
for i in 1 2 3 4 5 6 7 8 9; do
for j in 1 2 3 4 5 6 7 8 9; do
printf "%d*%d=%-2d " "$i" "$j" $((i*j))
done
echo
done
さいごに
ということで九九一覧表の作り方のふりをした「paste コマンドは、一般的には引数の複数のファイルを一行ずつ読み取って組み合わせて出力するコマンドですが、標準入力からの入力(-)を使うと n 個ごとに折り返すことができます」という記事でした。
一般的な使い方
$ cat foo.txt
foo1
foo2
foo3
# bar.txt と baz.txt も同様
$ paste foo.txt bar.txt baz.txt
foo1 bar1 baz1
foo2 bar2 baz2
foo3 bar3 baz3
この記事で紹介した使い方
$ seq 10 | paste - - -
1 2 3
4 5 6
7 8 9
10
このような使い方は POSIX でも紹介されています。(ls の出力結果を 4 つのカラムで出力する例)
Write out a directory in four columns:ls | paste - - - -
さて、他にもなにか面白い九九一覧表の作り方ないかな?
↧