Language detail: Bash

Coverage: 50.76%
number of '+' ratings
contribution for coverage

Unsolved challenges

codes

Feed

Used modules

next >>

シードを固定した乱数 (Nested Flatten)
BASH の RANDOM は数値を代入すると初期化されます。
1
2
3
#!/bin/bash
RANDOM=0
echo $RANDOM
バイナリクロック (Nested Flatten)

xbmで出力すればHHMMSSを16進にして流し込むだけで済むはず、との発想から。

xbmでは左から右に描くので、ビット左右反転をすべきなのですが ImageMagickで横着しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash 

date=`date '+%H %M %S'`

echo -e "#define b_width 6\n\
#define b_height 3\n\
static char b_bits[] = {\n\
"`printf '0x%X,' $date`"\n\
};" \
|display -flop -sample 120x240 -
6桁固定、時分秒。
{0,1}を並べることで2進数の列が得られます。
$ echo {0,1}{0,1}
00 01 10 11
あとは配列に入れれば10進→2進変換のできあがり。
1
2
3
4
5
bins=({□,■}{□,■}{□,■}{□,■}{□,■}{□,■})
time=(`date "+%H %M %S"`)
for i in 0 1 2; do
  echo ${bins[time[i]]}
done
もう少し短くしてみました。

 Linuxのprintf(シェルビルトインのものと /usr/bin/printf)では
フラグ文字 0と変換指定子 sを組み合わせても意図した結果が得ら
れなかったので、 dで代用しました。そのため、bcの返す値の最上
位桁が 0にならないことに依存します。

# AIX 4.3.3.0, HP-UX B.11.00, Linux 2.4.2, SunOS 5.5.1で動作
# を確認。
1
for t in `date '+%H %M %S'`; do printf '%06d\n' `echo "obase=2; $t" | bc` | tr '01' '.*'; done

しつこく強引な1liner

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function toBIN { \
  v=$1; \
  s=""; \
  while [ $v -gt 0 ];do \
    let "x = v>>1"; \
    let "b = v ^ x<<1"; \
    s=$b$s; \
    v=$x; \
  done; \
  echo $s; \
}; \
d=`date '+%H %M %S'`; \
c=" "; \
for V in `echo ${d}`;do \
  V=`toBIN $V`; \
  while [ ${#V} -lt 6 ];do \
    V=${c}${V}; \
  done; \
  echo ${V}|sed s/0/□/g|sed s/1/■/g; \
  c="0"; \
done;
16進数から10進数の変換 (Nested Flatten)

最大の整数は実装依存ですが、私の64bitマシンでは2^63-1が最大です。

1
2
3
4
5
6
7
8
9
h2i(){
  local -i i
  if [[ "$1" == 0x* ]]; then
    i="$1"
  else
    i=16#"$1"
  fi
  echo $i
}
手作業Grep (Nested Flatten)
1
2
3
4
5
6
#!/bin/sh
file=$(mktemp /tmp/handgrep.XXXXXXXXXX)
trap "rm -f $file" EXIT
cat > $file
(${EDITOR:-vi} $file < /dev/tty > /dev/tty)
cat $file
複素数 (Nested Flatten)

calc(apcalc)で。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ calc '( 3 + 1i ) + ( 4 - 1i )'
    7
$ calc '( 5 - 9i ) - ( 2 + 6i )'
    3-15i
$ calc '( 5 + 3i )  * ( 5 + 8i )'
    1+55i
$ calc '( 9 - 7i )  /  ( 9 - 3i )'
    ~1.13333333333333333333-0.4i
$ calc 'abs( 2 + 3i )'
    3.60555127546398929312
割り算の筆算 (Nested Flatten)
$ wari 12345 67
     184
  ------
67)12345
    67
  ------
    564
    536
  ------
     285
     268
  ------
      17
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
function wari() {
    local -i m=$1
    local -i n=$2
    local r=$(printf '%*d' ${#m} $((m / n)))
    write_head $m $n "$r"
    write_body $m $n "$r"
}

function write_head() {
    local m=$1
    local n=$2
    local r=$3

    repeat_char ' ' $((${#n} + 1))
    echo "$r"
    write_bar $m $n
    echo "$n)$m"
}

function write_body() {
    local m=$1
    local n=$2
    local r=$3
    local rest flag i

    for ((i = 0; i < ${#r}; i++)) {
        local c=${r:i:1}
        rest="$rest${m:i:1}"
        if [[ "$c" == [1-9] ]]; then
            [ -n "$flag" ] && printf '%*d\n' $((i + ${#n} + 2)) $rest
            printf '%*d\n' $((i + ${#n} + 2)) $((c * n))
            write_bar $m $n
            rest=$((rest - (c * n)))
            flag=1
        fi
    }
    [ -z "$flag" ] && write_bar $m $n
    printf '%*d\n' $((i + ${#n} + 1)) $rest
}

function write_bar() {
    local m=$1
    local n=$2
    repeat_char ' ' ${#n}
    repeat_char - $((${#m} + 1))
    echo
}

function repeat_char() {
    local c=$1
    local n=$2
    while ((n--)); do
        echo -n "$c"
    done
}
例外処理 (Nested Flatten)
以下の2要素を組み合わせました。

- エラーが起きた時点で実行を中断 → set -e
- それ(とシグナル)を捕捉 → trap、サブシェル

$ sh q245.sh
beginning of program
begenning of foo
begenning of bar
Catch!
end of program
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/sh

bar() {
  echo 'begenning of bar'
  [ 1 = 2 ]             # raise error
  echo 'end of bar'
}

foo() (                 # () runs subshell
  echo 'begenning of foo'

  # catch
  set -e
  trap 'echo "Catch!"' EXIT

  bar
  echo 'end of foo'
)

echo 'beginning of program'
foo
echo 'end of program'
ACLの制御 (Nested Flatten)

お題のタイトルに則って、POSIX ACLを設定します。

Linux 2.6 (POSIX ACL対応) + ext3 FS (mountオプションにaclを指定) で動作確認しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

filename=$1

if [ -e "$filename" ]; then
    if [ -f "$filename" ]; then
        chmod 600 "$filename"
        setfacl -b "$filename"
        setfacl -n -m u:$USER:rw "$filename"
    else
        echo "$filename is not file" 1>&2
        exit 1
    fi
else
    tmpdir=$(umask 077; mktemp -d acl.XXXXXXXX)
    (umask 077; touch "$tmpdir/$filename")
    setfacl -n -m u:$USER:rw "$tmpdir/$filename"
    mv "$tmpdir/$filename" .
    rmdir $tmpdir
fi
外部の実行ファイルを呼び出し (Nested Flatten)

すみません、ボケを思いつきませんでした。

1
2
3
4
5
# ブロックする
hoge

# ブロックしない
hoge &
ファイルサイズの取得 (Nested Flatten)

stat(1)で。

1
2
3
4
5
# GNU coreutils(Linux等)の場合
[ -f hoge.txt ] && stat -c %s hoge.txt

# FreeBSD系(Mac OS Xを含む)の場合
[ -f hoge.txt ] && stat -f %z hoge.txt
ローテートシフト (Nested Flatten)

tsekineさん、ナイスです。

ということでマージしてみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
printf -v minus_one_in_hex %x -1
typeset -i sizeof_long="${#minus_one_in_hex} * 4"
unset minus_one_in_hex

function rotR() {
    local i=$1
    local w=$2
    echo $((i >> w & ~(-1 << sizeof_long - w) | i << 64 - w))
}

function rotL() {
    local i=$1
    local w=$2
    echo $((i >> sizeof_long - w & ~(-1 << w) | i << w))
}
キッチンタイマー (Nested Flatten)
1
2
function timer { t=$1; while [ $t -gt 0 ]; do echo $t; t=`expr $t - 1`; sleep 1; clear; done; printf '\a'; }
timer 10

単にコマンドラインの次の行で、テキスト表示でカウントダウンするだけです。

キー操作:

  • SPC: 一時停止/再開
  • h、l: カーソルを左右(分・秒)に移動
  • k、j: カーソル位置の値(分・秒)を1つ増減
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/bin/bash

function dsp_time() {
    local t=$1
    echo -ne '\r'
    printf '%02.02d:%02d' $((t / 60)) $((t % 60))
    echo -ne '\r'
    [ "$cur_mode" = SEC ] && tput cuf 3
}

function timer_up() {
    if [ "$cur_mode" = MIN ]; then
        ((t_end += 60))
    else
        ((t_end += 1))
    fi
}

function timer_down() {
    if [ "$cur_mode" = MIN ]; then
        (((t_end - SECONDS - offset >= 60) && (t_end -= 60)))
    else
        (((t_end - SECONDS - offset >= 1) && (t_end -= 1)))
    fi
}

function key_command() {
    case "$c" in
    'h') cur_mode=MIN ;;
    'l') cur_mode=SEC ;;
    'k') timer_up ;;
    'j') timer_down ;;
    '') ((run_mode = run_mode == 1 ? 0 : 1)) ;;
    esac
}

trap 'stty cbreak echo' EXIT
stty -cbreak -echo

tm=420                  # 7 min
run_mode=1
cur_mode=MIN
offset=$SECONDS
t_end=$((offset + tm))
while ((tm > 0)); do
    dsp_time $tm
    read -n 1 -t 1 c && key_command "$c"
    if [ $run_mode = 1 ]; then
        ((tm = t_end - SECONDS - offset))
    else
        ((offset = t_end - tm - SECONDS))
    fi
done

dsp_time 0
echo
echo -ne '\a'
ローテートシフト (Nested Flatten)

long の bit 数は -1 の hex 表現から簡単に得られますよ。

1
2
local minus_one_in_hex=$(printf %x -1)
local -i sizeof_long="${#minus_one_in_hex} * 4"
整数(Cのlong)が64bitである前提です。

$ rotR 300 2
75
$ rotR -2 4
-1152921504606846977
$ rotL 300 4
4800
$ rotL -2 4
-17
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function rotR() {
    local i=$1
    local w=$2
    echo $((i >> w & ~(-1 << 64 - w) | i << 64 - w))
}

function rotL() {
    local i=$1
    local w=$2
    echo $((i >> 64 - w & ~(-1 << w) | i << w))
}
17歳教 (Nested Flatten)

たぶんGNU coreutilsのdate専用。

「何か月」の解釈は、date依存です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
bd=$1

nw=$(date +%s)
d=$(date -d "$bd 17 years" +%s)
m=-1

while ((d < nw)); do
    ((m++))
    ld=$d
    d=$(date -d "$(date -d @$d +%Y-%m-%d) 1 month" +%s)
done

echo -n '17歳と'
echo -n "$mか月と"
echo "$(((nw - ld) / 86400))"
masaka@ubuntu01:seventeen% jobs                        ~/work/doukaku/seventeen
masaka@ubuntu01:seventeen% cat 17.sh                   ~/work/doukaku/seventeen
#!/bin/bash
bd=$1

nw=$(date +%s)
d=$(date -d "$bd 17 years" +%s)
m=0

while ((d < nw)); do
    ((m++))
    ld=$d
    d=$(date -d "$(date -d @$d +%Y-%m-%d) 1 month" +%s)
done

echo -n '17歳と'
echo -n "$((m - 1)か月と"
echo "$(((nw - ld) / 86400))"
ナベアツ算 (Nested Flatten)

「アホになる」を縦ゆれ、「人探し」を横ゆれで表現してみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash

function AhoNiNaru() {
    local -i i
    for ((i = 0; i < 80; i++)) {
        tput indn 3
        tput rin 3
    }
}

function HitoSagashi() {
    local n=$1
    local -i i
    for ((i = 0; i < 70; i++)) {
        tput el1
        echo -n $n
    }
    echo
}

function NabeAtzz() {
    local -i n=$1

    tput clear
    tput cud 3

    local -i i
    for ((i = 1; i <= n; i++)) {
        if ((i % 8 == 0)); then
            HitoSagashi $i
        else
            echo $i
        fi
        if ((i % 3 == 0)) || [[ $i == *3* ]]; then
            AhoNiNaru
        fi
        sleep 1
    }
}

NabeAtzz 100
next >>

Index

Feed

Other

Link

Pathtraq

loading...