Memoize

BasicWerk   EC Support   Technique   Facebook  

20140813214931_shell_script_tips

shell_script_tips

 

構文チェック

 
% cat buggy.zsh
#! /bin/zsh
 
# わざと ] のあとの ; を抜かしてる
if [ -e hftfhvgch.lisp ] then
    echo hjgjgjgyj
fi
 
# -n オプションでデバッグ
% zsh -n buggy.zsh
buggy.zsh:5: parse error near `fi'
 

 

 

Mac の場合、シェルスクリプトの中から呼び出す echo とコマンドラインで呼び出す echo で -n オプションの認識が異なるらしい、bash では。

(zsh でコーディングしてると「ん?そうか?」と思う。)

 

ともあれ、改行なしの文字列を出力するときは printf の方が無難。

 
# 改行なし
% printf aaa
aaa%
# 最後の % は zsh が「改行文字は無いけどシェルの表示上改行するね」の意味
 
# 改行あり
% printf "aaa\n"
aaa
 

 

 

シェルスクリプトは、関数内だろうが変数はグローバルだ。

レキシカル変数化したい場合は local を使う。

 
% cat local.zsh
#! /bin/zsh
 
var="global"
 
function lex() {
    local var="in function"
    echo $var
}
 
# global
echo $var
 
# local
echo $(lex)
 
# one more global
echo $var
 
% local.zsh      
global
in function
global
 

 

 

変数や関数を外部ファイル化したなら、呼び出し側のスクリプトでは . コマンドで読みこめば良い。

 
#! /bin/zsh
 
. /path/to/lib.zsh
 

 

 

1行に全てのカラムが収まっていると判ってるデータで、特定のカラムを抜き出すなら awk より cut の方が書き方が簡単。

 
% cat sample.csv
1,item-A,2980,JPY
2,item-B,900,JPY
3,item-C,3980,JPY
4,item-D,1980,JPY
 
# 3番目のプライス部分だけ抜き出す
# -d セパレータ
# -f カラムナンバー
% cut -d, -f3 sample.csv
2980
900
3980
1980
 
# アイテム名とプライス
% cut -d, -f2,3 sample.csv
item-A,2980
item-B,900
item-C,3980
item-D,1980
 
# 同じことを awk でやると
% awk -F, '{ printf "%s,%d\n", $2, $3 }' sample.csv
item-A,2980
item-B,900
item-C,3980
item-D,1980
 
# 出力のフォーマットにこだわりがないならもうちょっとシンプルに書ける
% awk -F, '{ print $2,$3 }' sample.csv 
item-A 2980
item-B 900
item-C 3980
item-D 1980
 

 

 

$@ と $* の違い

 
% cat params.zsh
#! /bin/zsh
 
# 引数を個別にクォートして処理したいときは "$@" を使う
foreach arg ("$@")
    echo "@: $arg"
end
 
# "$*" はすべての引数が一つの文字列になる
echo "*: $*"
 
% params.zsh a b c
@: a
@: b
@: c
*: a b c
 

 

 

curl で http-status だけ欲しい場合は単に他の情報を捨ててしまえば良い。

 
% curl -s "http://basicwerk.com/memoize/" -o /dev/null -w "%{http_code}\n"
200
 

 

 

for ループは * や {...} で展開した結果を一つの配列とみなして動作してくれる。

 
% ls *.csv
data.csv
data_replaced.csv
sample.csv
 
for csv in *.csv
do
    wc -l $csv
done
# result
1918136 data.csv
1918136 data_replaced.csv
4 sample.csv
 
% ls sample2/
file_1		file_2		file_3		other_1		other_2		other_3
 
for file in sample2/file_{1..3}
do
    echo "this is a file" > $file
done
 
% cat sample2/file_{1..3}
this is a file
this is a file
this is a file
 

 

 

これらの Tips は全てこちらの本をだーっと読んで拾ったものです。

 

 

 

ちなみに本自体は bash で記述してあるが、僕が使ってるのが zsh なので敢えて zsh で動作を確認してみた。

 

 


© Shin Nakamura/BasicWerk 2014