• シェルプログラミング?

概要

下位ページ

  • parallel?

目次

デバッグ

  • 下らないミスをなくすために、必ず以下をかくこと
    #!/bin/bash
  • コマンド展開
    sh -x test_eval_1.sh #展開後実際に起きていることがわかる

bashとshの違い

  • リダイレクト先にメタ記号を使えない

文法

if

if [ $? -eq 1 ] # []の回りにスペース必須
then
   continue
fi  

for

  • for文ではcontinue可能

終了ステータス

  • $?で終了ステータス
    • grepで見つかったかどうかなどが分かる

配列

list=("1332" "1333" "1605") # =の間にスペースを入れると死ぬ

include

. list #listは実行可能である必要は無い

find

find .
find . -type f
find . -type ! -name "*~"
find . -type f -a \( -name "*.c" -o -name "*.h" \)
  • なぜかfind . -type ! -name *~は動作しない。
    • hoge*, "hoge*", 'hoge*'の違いが知りたい
    • $"とかもあるの?"

xargs

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

  • オプション-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

  • awkで置換
echo "replot" | awk '{sub(/^rep/, "p", $0); print $0}'

make

Makefileの\( のエスケープは \)$

backquote

echo hamu
echo `echo hamu`
echo `echo \`echo hamu\``
echo `echo \`echo \\\`echo hamu \\\`\``

for文

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を食ってしまう。

セパレータ

#!/bin/bash IFS=$'\n' for i in `cat file` do IFS=$' \t\n'で echo $i done

$''

中の\t, \b, \nなどを展開する。
これはalt-v [tab], alt-v [backspace], alt-v [enter]に相当する。

echo "a\na"
\n
echo $'a\na'
a
a

while

while read i;do echo $i;done < file 
  • 1行の場合は、doの後に;を入れてはならない

文字列の比較

${var} = "A" ${var} != "A"

  • if [ ${var} = A ]と何が違うの?違わないとしたら""の意味は何?

何もしない

:

if

  • 中のコマンド実行結果が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

  • testと[は同じ意味。
if [ condition ] 
then
    expression
fi
if  [ -e hoge ] ; then echo a ; fi
  • 一行の時はthenの後に改行を入れてはならない。

grep, egrep

  • 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

$?とパイプ

echo "hoge" | grep "test" | echo $?
  • 出力をechoが食おうとしているから、grepの終了コード1を正常に取得できない。
    echo "test" | grep "test" ; echo $?
  • grepが終わってからechoしているので、1が表示される

Gnuplot

plot "file" u 1
plot "file" u ($1)
  • uの後は、カッコでくくると式モードになって、1などは$1などにしなければいけなくなる。

for

  • a
1 2 3
2 3 2
3 5 2
5 8 1
plot for [i=1:3] "a" u i

sprintf

plot for [i=1:3] sprintf("hoge%02d", i) t sprintf("hoge%02d", i)
  • hoge01, hoge02, ...をplot

system

  • num.config
3
num = system("cat num.config")
plot for [i=1:num] sprintf("hoge%02d", i) t sprintf("hoge%02d", i)

数字と文字列の連結

n = system("awk '{print NF; exit}' motenc_state")
replot for [i=2:n] "dv_motor" u i title "Motenc State".(i-1)." [unknown]"

awk

1行目のフィールド数の取得

awk '{print NF; exit}' file

complete

complete

complete -o dirnames -f -X '!*.mp3' mp3nantoka.sh
  • COMPREPLYの中を候補に表示する「だけ」
    comptest2 () {
        COMPREPLY=( aaa bbb )
    }
    complete -F comptest2 hoge
    hoge [tab][tab]

comgen

  • aaa, bbbを候補に表示し、補完
    comptest1 () {
        COMPREPLY=( `compgen -W "aaa bbb" $2` )
    }
    complete -F comptest1 hoge
    hoge [tab][tab]

定石

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のパスの場合

complete -F "_plotter" -o "nospace" "plotter"
  • nospaceのoptionをつけると、最後にスペースが入らなくて良い

Dropbox

~/.dropbox-dist/dropboxd

自動起動

Startup Aplicationからクリックで頑張る

wget

  • URLのソースコードを取得する
    wget https://twitter.com/

cron

  • cronの設定を行う。書式はググる。
    crontab -e
    crontab -l
    • cron_has_calledはデフォルトでhomeに出力されるようになっている。
      23 * * * * echo "hallo" >> cron_has_called

mail

echo "test" | mail wakataberyo@gmail.com

sendmail

  • headerを明示的に書く必要があるのと、mailに比べて愚直である。
  • headerの例(最後は改行が必要)
    Content-Type: text/plain; charset=iso-2022-jp
    Subject: test
    
  • 使い方
    cat header honbun | sendmail wakataberyo@gmail.com

md5sum

  • 文字列をハッシュにする。
    echo "test" | md5sum
    d8e8fca2dc0f896fd7cb4cb0031ba249  -
  • ハイフンには標準入力という意味がある。

iconv, nkf

  • 文字コード変換
  • 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

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS