この記事は約15分30秒で読むことができます。

機能的には指定回数コマンドを繰り返すだけのスクリプトになってしまった話

参考文献

このサイト楽しいんですけど

Linux: Repeat Command N Times – Bash FOR Loop  

何回もみさせてもらっています。

位置パラメーターの一括展開の違いを知れ!!  

まえがき

機能的には指定回数コマンド繰り返すだけのスクリプトになってしまったけど、”$@”と”$*”違いを意識しながらかけた(つもりになっている)”$@”ではなく”$*”の方が組込変数とか組み込んで展開されるから、今回は”$@”が作りたかった方になる。

ast

コード表示

[root@c10c717ad069 wk]# cat as*
#/bin/bash
usg(){
  clr="${1}"
  shift
  case "${*}" in
    'runerr') fmtclr "${clr}" "$(prt 'syntax err.chk caller cmd.')";exit 1;;
    'argchk') fmtclr "${clr}" "$(prt 'chk args.must 2 args.primary arg is run time.secondary arg is cmd.')";exit 1;;
    'success') fmtclr "${clr}" "$(prt 'successfully done.')";exit 0;;
  esac
}

fmtclr(){
  local clr_nm clr
  [ "${#}" -eq 2 ] || usg 'argchk'
  readonly clr_nm="${1}"
  shift
  case "${clr_nm}" in
    red) clr=31;;
    green) clr=32;;
    yellow) clr=33;;
    cyan) clr=36;;
    white) clr=37;;
    magenta) clr=95;;
    *) clr=30;;
  esac
  printf "\033[${clr}m%b\033[m\n" "${*}"
}

hdl(){
  local clr_nm typ cmd
  [ "${#}" -eq 2 ] || usg 'argchk'
  clr="${1}"
  shift
  readonly typ="${*}"
  case "${typ}" in
    runerr) choice_clr="${clr}";;
    argchk) choice_clr="${clr}";;
    success) choice_clr="${clr}";;
    *) :;;
  esac
  cmd="usg"
  ${cmd} "${choice_clr}" "${typ}"
}

prt(){
  local msg
  [ "${#}" -eq 1 ] || usg 'argchk'
  readonly msg="$1"
  echo "-----${msg}-----"
}

run(){
  cxt "${*}"
  local rpt cmd
  echo $(fmtclr 'magenta' "_____args:${#}_____")
  [ "${#}" -eq 2 ] || hdl 'yellow' 'argchk'
  rpt="${1}"
  echo $(fmtclr 'magenta' "_____rpt:${rpt}_____")
  shift
  cmd="${*}"
  echo $(fmtclr 'magenta' "_____cmd:${cmd}_____")
  for i in $(seq "${rpt}");do
    bash -c "${cmd}"
    [ "${?}" -eq 0 ] || hdl 'red' 'runerr'
  done
  [ "${?}" -ne 0 ] || hdl 'green' 'success'
}

cxt(){
  slf=$0
  echo $(fmtclr 'white' "-----${slf#*/}-----")
  echo $(fmtclr 'white' "_____args:${#}_____")
  echo $(fmtclr 'white' "_____args..is:[${*}]_____")
}

run "${*}"

atm

コード表示

[root@c10c717ad069 wk]# cat at*
#/bin/bash
usg(){
  clr="${1}"
  shift
  case "${*}" in
    'runerr') fmtclr "${clr}" "$(prt 'syntax err.chk caller cmd.')";exit 1;;
    'argchk') fmtclr "${clr}" "$(prt 'chk args.must 2 args.primary arg is run time.secondary arg is cmd.')";exit 1;;
    'success') fmtclr "${clr}" "$(prt 'successfully done.')";exit 0;;
  esac
}

fmtclr(){
  local clr_nm clr
  [ "${#}" -eq 2 ] || usg 'argchk'
  readonly clr_nm="${1}"
  shift
  case "${clr_nm}" in
    red) clr=31;;
    green) clr=32;;
    yellow) clr=33;;
    cyan) clr=36;;
    white) clr=37;;
    magenta) clr=95;;
    *) clr=30;;
  esac
  printf "\033[${clr}m%b\033[m\n" "${*}"
}

hdl(){
  local clr_nm typ cmd
  [ "${#}" -eq 2 ] || usg 'argchk'
  clr="${1}"
  shift
  readonly typ="${*}"
  case "${typ}" in
    runerr) choice_clr="${clr}";;
    argchk) choice_clr="${clr}";;
    success) choice_clr="${clr}";;
    *) :;;
  esac
  cmd="usg"
  ${cmd} "${choice_clr}" "${typ}"
}

prt(){
  local msg
  [ "${#}" -eq 1 ] || usg 'argchk'
  readonly msg="$1"
  echo "-----${msg}-----"
}

run(){
  cxt "${@}"
  local rpt cmd
  echo $(fmtclr 'magenta' "_____args:${#}_____")
  [ "${#}" -eq 2 ] || hdl 'yellow' 'argchk'
  rpt="${1}"
  echo $(fmtclr 'magenta' "_____rpt:${rpt}_____")
  shift
  cmd="${*}"
  echo $(fmtclr 'magenta' "_____cmd:${cmd}_____")
  for i in $(seq "${rpt}");do
    bash -c "${cmd}"
    [ "${?}" -eq 0 ] || hdl 'red' 'runerr'
  done
  [ "${?}" -ne 0 ] || hdl 'green' 'success'
}

cxt(){
  slf=$0
  echo $(fmtclr 'white' "-----${slf#*/}-----")
  echo $(fmtclr 'white' "_____args:${#}_____")
  echo $(fmtclr 'white' "_____args..is:[${@}]_____")
}

run "${@}"

実行例

コード表示

[root@c10c717ad069 wk]# time { for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"echo hoge\"; "; }
-----ast.sh-----
_____args:1_____
_____args..is:[3 echo hoge]_____
_____args:1_____
-----chk args.must 2 args.primary arg is run time.secondary arg is cmd.-----
-----atm.sh-----
_____args:2_____
_____args..is:[3 echo hoge]_____
_____args:2_____
_____rpt:3_____
_____cmd:echo hoge_____
hoge
hoge
hoge
-----successfully done.-----

real	0m10.016s
user	0m0.011s
sys	0m0.006s

diff

diffだよ

コード表示

[root@c10c717ad069 wk]# diff as* at*
53c53
<   cxt "${*}"
---
>   cxt "${@}"
73c73
<   echo $(fmtclr 'white' "_____args..is:[${*}]_____")
---
>   echo $(fmtclr 'white' "_____args..is:[${@}]_____")
76c76
< run "${*}"
---
> run "${@}"
[root@c10c717ad069 wk]# diff -y as* at* | nl

エラーのハンドリングむずかしいシェル

こういいうの実行すると、よろしくない動きするから、まだまだ構文解析的な予測の仕方が足りないことがわかる。コンパイラ作る人すげ。思ったけど、ASCII文字から覚えっていった方が、別の視点でプログラム書けるようになるかも、やってみよ。エスケープの癖を上手く回避できるようになるかも、最小限で。個人的にはメッセージの関数は可変長引数にしたかったけど、いったんここまで。テストケース↓。

コード表示

[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"echo hoge\"; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"eco hoge\"; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"\"; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"\" \"\"; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[]; "
[root@c10c717ad069 wk]# for i in *;do echo $i; done | xargs -I[] bash -c "sleep 5;./[] \"3\" \"echo hoge\"; "

Leave a Reply

Your email address will not be published. Required fields are marked *