- 追加された行はこの色です。
- 削除された行はこの色です。
// 検索用:シェルスクリプト
-[[シェルプログラミング]]
*概要 [#fc9dc96c]
-ShellScriptの書き方
-bashができれば大体shもできるので、bashメイン
-[[シェル芸の問題と解答を公開しているサイトがある>https://blog.ueda.asia/?page_id=1434]]
*下位ページ [#u40b2348]
-[[parallel]]
*目次 [#r1aa2f8f]
#contents
*デバッグ [#ce6b68df]
-''下らないミスをなくすために、必ず以下をかくこと''
#!/bin/bash
-コマンド展開
sh -x test_eval_1.sh #展開後実際に起きていることがわかる
*bashとshの違い [#kd458d71]
-リダイレクト先にメタ記号を使えない
*文法 [#k4b2ce77]
**if [#r2c7666a]
if [ $? -eq 1 ] # []の回りにスペース必須
then
continue
fi
**for [#ffbb6397]
-for文ではcontinue可能
**終了ステータス [#pd463b87]
-$?で終了ステータス
--grepで見つかったかどうかなどが分かる
**配列 [#p79c8cfc]
list=("1332" "1333" "1605") # =の間にスペースを入れると死ぬ
**include [#t49c5f59]
. list #listは実行可能である必要は無い
*find [#u16ed6c4]
find .
find . -type f
find . -type ! -name "*~"
find . -type f -a \( -name "*.c" -o -name "*.h" \)
-なぜかfind . -type ! -name *~は動作しない。
--hoge*, "hoge*", 'hoge*'の違いが知りたい
--$"とかもあるの?"
*xargs [#r5740fd6]
ls -1 | xargs echo
find . -print0 | xargs -0 echo
find . -print0 | xargs -0 -L1 echo
find . -print0 | xargs -0 -L2 echo
find . -print0 | xargs -0 -I{} echo "<{}>"
-findからxargsにパイプする場合は、絶対findの$最後に$-print0をいれてxargsに-0を入れる。
ls | sed -e "p;s/\.jpeg$/\.jpg/" | xargs -n2 mv
for i in *.jpeg ; do mv $i `basename $i .jpeg`.jpg ; done
-頑張ってmv, cpなどの二つ同じものが出てくる場合は、このようにsedの;セパレータと-n2で頑張る
--sifiたんありがとうございます。
*sed [#nf83901b]
-オプション-Eで拡張正規表現も使える。
sed -e 's/#//'
-Hitしなければそのまま表示、Hitすれば処理をして表示
sed -n 's/#//'
-Hitしてもしなくても非表示
sed -n 's/#//p'
-Hitすれば処理をして表示
--そもそもHitしているか、何回Hitしているかを確認するために、-eにpをつけることもある。
echo 'a a' | sed -e 's/ *//'
-出力は"a a"
--なぜなら、1つ目のaの前にマッチするから。
sed -e '1s/rep/p/'
-1行目のrepをpに変換
--行数の指定は一番初めに書く。指定方法は
---1: 1行目
---1,10: 1行目から10行目
---1,+10: 1行目から11行目
---^,$: 行頭から行末まで
--など
-sedは{とか}をエスケープ必要がある
--でもgrepはそうでもない
--どういうのがエスケープ必要で、必要ないの?
--Sedは1行でマッチする文字が何通りもある場合は、一番長いものにマッチする。(sed ‘[l],[r]s/<[^<]*>//’の時、前半はオンオフで制御され、後半はきちんと最長一致で制御されている。)
*awk [#h7233819]
-awkで置換
echo "replot" | awk '{sub(/^rep/, "p", $0); print $0}'
*make [#x6fb5be5]
Makefileの$のエスケープは$$
*backquote [#l969c4cb]
echo hamu
echo `echo hamu`
echo `echo \`echo hamu\``
echo `echo \`echo \\\`echo hamu \\\`\``
*for文 [#p2ca5082]
for var in `echo "a b"`
do
echo ${var}
done
for var in `echo "a b"` ; do echo ${var} ; done
-1行の場合は、doの後に;を入れてはならない
-1行にする場合は二つ目のechoの後の;が必須。ないとechoがdoneを食ってしまう。
*セパレータ [#zfc117e2]
#!/bin/bash
IFS=$'\n'
for i in `cat file`
do
IFS=$' \t\n'で
echo $i
done
* $'' [#k2bcd27c]
中の\t, \b, \nなどを展開する。~
これはalt-v [tab], alt-v [backspace], alt-v [enter]に相当する。~
echo "a\na"
\n
echo $'a\na'
a
a
* while [#k4a395c3]
while read i;do echo $i;done < file
-1行の場合は、doの後に;を入れてはならない
*文字列の比較 [#uaeea0c4]
${var} = "A"
${var} != "A"
-if [ ${var} = A ]と何が違うの?違わないとしたら""の意味は何?
*何もしない [#d1655e85]
:
*if [#c1fe8662]
-中のコマンド実行結果が0ならthenを実行する構文。
if command
then
expression
fi
if command ; then echo a ; fi
-空文字列判定
if [ -z "${opts}" ]; then
echo "null stream"
else
echo "not null stream"
fi
-空ファイル判定
if [ -s test.txt ]; then
echo "exist"
else
echo "not exist"
fi
-ダブルクオーテーションで囲まないとだめ
*test [#ka1ed772]
-testと[は同じ意味。
if [ condition ]
then
expression
fi
if [ -e hoge ] ; then echo a ; fi
-一行の時はthenの後に改行を入れてはならない。
*grep, egrep [#d65fa98d]
-egrepはgrepの正規表現が新しいバージョン。+, ?が使える。~
-実行結果は、検索に引っかかったら0, 引っかからなかったら1
echo $' \t' | grep $'^[ \t]+$' ; echo $?
1
echo $' \t' | egrep $'^[ \t]+$' ; echo $?
0
-ちなみに-Eをつけるとegrepと同じ動作に
--これはsedでも同じ挙動をする
echo $' \t' | grep -E $'^[ \t]+$' ; echo $?
1
*$?とパイプ [#b40c18e9]
echo "hoge" | grep "test" | echo $?
-出力をechoが食おうとしているから、grepの終了コード1を正常に取得できない。
echo "test" | grep "test" ; echo $?
-grepが終わってからechoしているので、1が表示される
*Gnuplot [#t558cb62]
**式 [#oa960a00]
plot "file" u 1
plot "file" u ($1)
-uの後は、カッコでくくると式モードになって、1などは$1などにしなければいけなくなる。
**for [#x65e72f2]
-a
1 2 3
2 3 2
3 5 2
5 8 1
plot for [i=1:3] "a" u i
**sprintf [#j6e08031]
plot for [i=1:3] sprintf("hoge%02d", i) t sprintf("hoge%02d", i)
-hoge01, hoge02, ...をplot
**system [#m0de8670]
-num.config
3
num = system("cat num.config")
plot for [i=1:num] sprintf("hoge%02d", i) t sprintf("hoge%02d", i)
**数字と文字列の連結 [#c281e897]
n = system("awk '{print NF; exit}' motenc_state")
replot for [i=2:n] "dv_motor" u i title "Motenc State".(i-1)." [unknown]"
*awk [#c267cf70]
**1行目のフィールド数の取得 [#kb24f72c]
awk '{print NF; exit}' file
*complete [#uc6529f6]
**complete [#d82ec31d]
complete -o dirnames -f -X '!*.mp3' mp3nantoka.sh
-COMPREPLYの中を候補に表示する「だけ」
comptest2 () {
COMPREPLY=( aaa bbb )
}
complete -F comptest2 hoge
hoge [tab][tab]
**comgen [#q7595d2b]
-aaa, bbbを候補に表示し、補完
comptest1 () {
COMPREPLY=( `compgen -W "aaa bbb" $2` )
}
complete -F comptest1 hoge
hoge [tab][tab]
**定石 [#y47f6b13]
function _hoge {
local arg opts
COMPREPLY=()
arg="${COMP_WORDS[COMP_CWORD]}"
opts="`ls -1`"
IFS=$'\n'
COMPREPLY=($(compgen -W "${opts}" -- ${arg}))
unset IFS
}
complete -F "_hoge" "hoge"
**Directoryのパスの場合 [#n67f5b4f]
complete -F "_plotter" -o "nospace" "plotter"
-nospaceのoptionをつけると、最後にスペースが入らなくて良い
*Dropbox [#i7ad47e7]
~/.dropbox-dist/dropboxd
*自動起動 [#r22b5c8e]
Startup Aplicationからクリックで頑張る
*wget [#a55b816b]
-URLのソースコードを取得する
wget https://twitter.com/
*cron [#x371505d]
-cronの設定を行う。書式はググる。
crontab -e
crontab -l
-例
--cron_has_calledはデフォルトでhomeに出力されるようになっている。
23 * * * * echo "hallo" >> cron_has_called
*mail [#we0733a2]
echo "test" | mail wakataberyo@gmail.com
*sendmail [#m48aac2b]
-headerを明示的に書く必要があるのと、mailに比べて愚直である。
-headerの例(最後は改行が必要)
Content-Type: text/plain; charset=iso-2022-jp
Subject: test
-使い方
cat header honbun | sendmail wakataberyo@gmail.com
*md5sum [#i912ec90]
-文字列をハッシュにする。
echo "test" | md5sum
d8e8fca2dc0f896fd7cb4cb0031ba249 -
-ハイフンには標準入力という意味がある。
*iconv, nkf [#qd24fdf2]
-文字コード変換
-iconv
--文字コードをFROMからTOにする。
--半角カナ文字が入っていると対応できないので、日本語を扱うときには基本的にnkfを使う。
iconv -f FROM -t TO
-nkf
--文字コードをguessしてISO-2022-jpにする
cat file | nkf -j
--文字コードをguessしてSHIFT-JISにする
cat file | nkf -s