naobe @ ウィキ

ksh

最終更新:

Bot(ページ名リンク)

- view
管理者のみ編集可
Linuxに戻る


.profile

ログイン起動スクリプト

.kshrc

シェル初期起動スクリプト。/bin/kshを手動で実行したときに動くスクリプト。
【設定例】
 PATH=$PATH:.
 # fcを実行したときのエディタ
 export FCEDIT=vi
 # Emacsモード。履歴を修正するときにEmacsのキーバインディングを使用可能
 set -o emacs
 
 alias l='ls -F'
 alias ll='ls -alt'
 alias rm='rm -i'

プロンプトの変更

.profileに以下を追加すると、[ユーザ@ホスト 現ディレクトリ]$ がプロンプトになる。
 PS1='[$USER@$HOSTNAME ${PWD##*/}]\$ '


履歴

historyコマンドで、過去のコマンド履歴表示。historyはfc -lのalias。bashと機能は同じではないかな?

 history 10  履歴番号10以後すべて表示
 history -10 過去10件の履歴表示
 history 10 10 履歴番号10を表示
 history 10 100 10~100の履歴を表示

 $ history
 322     ps -ef
 323     ps -ef | grep back
 324     print -p 2
 325     read-p x
 326     read -p x
 327     read -p
 328     ps -ef | grep back
 329     ps -ef | grep back
 330     kill 23262
 331     ps -ef | grep back
 332     history
 333     321
 334     !321
 335     man ksh
 336     man history
 337     history

FCEDIT=/bin/viとしておくと、fc 履歴番号 で、viにコマンド表示。viで編集して終了すれば、コマンドを実行する(途中やめできない。編集しなければ前のコマンドを実行するので注意が必要。)。直近の履歴なら、set -o emacsにしておいて上矢印でコマンド履歴をたどれる。

安全に実行できるスクリプトを作成してみた。
 #!/bin/ksh
 #
 # 履歴を指定して過去のコマンドをファイルに格納する。
 # 対話的に実行を確認して、編集後のコマンドを実行する。
 #
 usage() {
     echo "usage: rireki history_num $1"
 }
 
 exec_cmd() {
     .  /tmp/${USER}_cmdline
 }
 
 ptn_match() {
     echo $1 | egrep -q $2
 }
 
 if [ $# -eq 0 ]; then
     usage ;
     exit 1
 fi
 
 ptn_match $1 '^[1-9][0-9]+'
 if [ $? -ne 0 ] ; then
     usage "引数が数値でない"
     exit 1
 fi
 
 HISTORY_NO=$1
 fc -ln $HISTORY_NO $HISTORY_NO > /tmp/${USER}_cmdline
 echo -n "コマンドを保管しました。コマンドを編集しますか(y/n) "
 read ANS
 ptn_match $ANS '^(y|yes)$'
 if [ $? -eq 0 ]; then
     vi  /tmp/${USER}_cmdline
     echo -n "実行しますか(y/n) "
     read ANS2
     ptn_match $ANS2 '^(y|yes)$'
     if [ $? -ne 0 ]; then
         exit 0
     fi
     exec_cmd ;
 else
     exec_cmd ;
 fi

スクリプト

((...))構文

(())の中で、C言語と同様の計算式を使える。戻り値はtruer/falseで、if, whileの条件式として使える。forの条件としても使える。(())の中では変数を表すのに$は不要(あっても構わない)。$((...))は計算式の結果を変数として扱う。
 for(( i = 0 ; i <10 ; i++ ))
 do
     echo $i
 done
 
 AA=$((1.5 + 2.2))
 echo $AA
 
 ((AA = 1.5 + 2.2))
 echo $AA
 
 #
 echo 計算式の評価
 r=30
 echo r = $r
 ((pi = 4.0 * ( 4.0 * atan(1.0/5.0) - atan(1.0/239.0) )))
 echo pi = $pi
 ((enshu = pi * 2 * r))
 echo enshu = $enshu
 echo

この機能はabs、acos、asin、atan、cos、cosh、exp、int、log、sin、sinh、sqrt、tan、tanhなどの数学関数と一緒に利用できる。

ループ

Bourn Shellと同様
 【例】
 while
 #
 # コマンドパラメータを順次出力
 #
 for param
 do
     echo $param
 done
 #
 #  ファイル読み込み
 #
 #     改行文字がセパレータなので1行ごとに表示される。
 #     何故か、この場合、ブランク、タブはセパレート文字にならない
 #
 #for line in `cat /etc/passwd`
 for line in $(cat /etc/passwd)
 do
     echo $line
 done
 for(( i = 0 ; i < 10 ; i++ ))
 do
     echo $i
 done

 #
 #  select, ifテスト
 #
 select name in aaa bbb ccc
 do
     echo $name
     # パターン一致ではない
     if [[ $name == ccc ]]
     then
         break
     fi
 done
 #
 #  select, ifテスト
 #
 select name in aaa bbb ccc
 do
     echo $name
     # パターン一致ではない
     if echo $name | egrep -q '^cc.*'
     then
         break
     fi
 done
 #
 #  caseテスト
 #
 read name
 case $name in
 aaa)
     echo AAA
 ;;
 bbb)
     echo BBB
 ;;
 esac
 #
 #  while
 #
 file="/etc/passwd"
 IFS=:
 while read user passwd userid grpid comment homedir interpret
 do
     echo $user $homedir $interpret
 done < $file
 

変数

typeset

関数内で使用すると、ローカル変数になる。関数は、function func_nameの形式で書かないと有効にならない(CentOS)。
 【例】
 #
 # typeset フォーマット変換
 #
 name=abc
 name2=abc
 number1=123
 
 #  左詰め、桁数5
 typeset -L5 name
 echo "###$name###"
 
 typeset -L5 name=def
 echo "###$name###"
 
 # 右詰、桁数5
 typeset -R5 name2
 echo "###$name2###"
 
 # 右詰、桁数8、0埋め
 typeset -Z8 number1
 echo "###$number1###"
 【実行結果】
 ###abc  ###
 ###def  ###
 ###  abc###
 ###00000123###

単純な変数

【例】
 echo 単純な変数
 var=aaa
 echo $var
 echo

複合変数

構造体のような変数
【例】
 #!/bin/ksh
 person=(
     name=""
     sex="male"
     age=""
 )
 
 eval "bill=$person"
 bill.name=bill
 bill.age=32
 
 eval "sally=$person"
 sally.name=sally
 sally.sex=female
 sally.age=21
 
 echo "bill: name=${bill.name} sex=${bill.sex} age=${bill.age}"
 echo "sally: name=${sally.name} sex=${sally.sex} age=${sally.age}"

配列

【例】
 #
 #    配列
 #
 echo 一度に代入
 array=(a b c d)
 #
 # 中括弧を記述しないと、$arrayが先に評価される。
 echo ${array[0]}
 echo $array
 echo ${array[3]}
 echo ${array[*]}
 echo
 #
 echo 個々に代入
 array[0]=A
 array[1]=B
 array[2]=C
 echo ${array[0]}
 echo ${array[1]}
 echo ${array[2]}
 echo
 

連想配列

【例】
 #
 echo 連想配列
 typeset -A hash
 hash=([key1]=val1
 [key2]=val2
 [key3]=val3)
 echo hash[key1]=${hash[key1]}
 echo hash[key2]=${hash[key2]}
 echo hash[key3]=${hash[key3]}
 echo
 

関数

基本的な関数

 【例】
 #
 #  基本的な関数
 function add {
     return `expr $1 + $2`
 }
 
 
 add 1 2
 echo 1 + 2 = $?

ディシプリン関数

変数をget,set,unsetしたときに起動する関数。変数の値を自動的に変える。たとえば円の半径を変えた時に演習を自動的に変えたいときに使う。変数の値はシェルの特殊変数である.sh.valueに設定する。
 #
 # 半径から円周、面積を求める
 ((pi = 4.0 * ( 4.0 * atan(1.0/5.0) - atan(1.0/239.0) )))
 ## 複合変数
 en=(
 float hankei
 float enshu
 float menseki
 )
 
 #
 #  円周のディシプリン関数
 function en.enshu.get {
     (( .sh.value = 2 * pi * en.hankei ))
 }
 
 en.hankei=2.
 echo hankei : ${en.hankei}
 #
 #  円周を求めるときにディシプリン関数が起動される(半径を変えると自動的に円周が変わる)。
 echo enshu : ${en.enshu}

コプロセス

コプロセスとは、双方向のパイプ。|&を使って、プロセスをバックグラウンドで起動すると、print -p, read -pを使ってバックグラウンドプロセスとデータのやりとりができる。
 【例】
 back.sh
 	total=0
 	while ["" == ""]
 	do
 		read input
  		(( total = total + input ))
  		echo $total
 	done
 
 $./back.sh |&
 $ print -p 2
 $ read -p x; echo $x
 2
 $ print -p 10
 $ read -p x; echo $x
 12
 $ print -p 100
 $ read -p x; echo $x
 112
人気記事ランキング
ウィキ募集バナー