忍者ブログ
Yaleで、遊んで学ぶ日々。

Yaleで、遊んで学ぶ日々。

囲碁、ときどきプログラミング、ところにより経済。
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

余談ですが、シェルスクリプトの関数って定義の中で自分を使えるんですね。出来そうだな、と思って実験してみたらやっぱりできました。
前の記事でも使っています。

下のtest.shというのがその例です。
funという関数を定義する中で、fun関数自身を使っています。
つまり、funを使おうと思ったらそのためにfunを使わなくてはいけなくって、またそのためにfunを使い、さらにまたそのために…ということになり、放っておくと永遠に処理が終わりません。
永遠の繰り返しを避けるために  if節を使って処理を2000回で終わらせています。この if節がなければ無限に数を数えつづける無限ループです。ハマってしまったら Ctrl+C で抜けだせます。


この例だと、funという関数は結局定義されず終いなんですよね。
自分の定義の中で自分を使ってしまっては、定義にならないのは当然です。
funという関数の実態はあやふやなまま、ただ「関数が呼ばれたらプログラムのこの場所へ移動」という動作だけがはっきりしています。

Pythonでまったく同じことを試してみたところ、繰り返しが1000を越えるとエラーが出ました。エラーの内容は、"RuntimeError: maximum recursion depth exceeded" だそうです。限られた回数なら定義内で自分を参照することが許されているというわけですね。確かに、終わりがちゃんと来るのであれば定義は曖昧ではありません。動的計画法で使うBellman Equationと同じです。Recursiveな定義も収束さえすれば定義たりうるというわけです。

これが手続き型とオブジェクト指向の違いなんでしょうか(違うかも)。
シェルスクリプトでは、関数は手順を示すものに過ぎませんが、pythonでは関数も1つのオブジェクトなので、実態があります。無限に自己参照を繰り返すオブジェクトは有効に定義されず、認められません(きっと1000回というのが無限と擬似される現実的な境目なのでしょう)。


人間のアイデンティティも同じで、多くの場合、自分の立ち位置を確認するためには他者を参照せざるをえません。自己完結は頑健なようで、案外脆いのかもしれません。



test.sh

#!/bin/sh

fun()
{
    if [ $1 -gt 1999 ]
    then
        return
    fi

    echo $1
    x=`expr $1 + 1`
    fun $x
}

fun 0




test.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*-


def fun(x):
    if x > 999: # try 998 too
        return ""
   
    print x
    fun(x+1)
   
   
fun(0)



PR
Windows用のTextTreeというフリーソフトを愛用していました。
ルートディレクトリを定めてやると、そこ以下のテキストファイルをツリー上に表示してくれて、閲覧および編集ができるというソフトです。
僕は研究上のアイデアを書き留めたり、プログラミングのtipsをメモするなどの用途で使っていました。
使った感じはAUTLAなどのアウトラインプロセッサとほぼ同じです。
シンプルで動きが軽快なのでTextTreeの方が好きでした。


Linuxでは、gjots2というソフトがTextTreeと同様の機能を提供してくれます。
gjots2はアウトラインプロセッサで、UbuntuならSynaptic Package Managerからインストールできます。
今日はTextTreeからgjots2への移行を行いました。


2つのソフトウェアの大きな相違点は、TextTreeがディレクトリの階層構造を解釈しているのに対し、gjots2(及びその他のアウトラインプロセッサ)は内部に階層構造を持った1つのテキストファイルに情報を保存しているということです。
TextTreeでは、各記事の情報は別々のファイルに保存されています。したがって、他のテキストエディタで個別のファイルを閲覧、編集することも可能です。ツリーの構造には、ディレクトリ構造がそのまま反映されます。
gjots2の場合、記事の中身からツリーの構造までのすべての情報は1つのテキストファイルに保存されます。このファイルを他のエディタで開くことも可能ですが、ちょっとしたプログラム言語調で書かれているのでぱっと見ではツリー構造までは分かりません。下手に編集するとツリー構造を壊す恐れもあるので注意が必要です。興味のある人は開いてみるとよいと思います。


そういうわけで、移行するためにはTextTreeで使っていたディレクトリの構造を、gjots2で使われている「文法」で書き換える必要があります。その作業はシェルスクリプトで行いました。
TextTreeを使っていたけどLinuxを始めて代わりにgjots2を使い始めた人にしか必要がないスクリプトので、需要はほぼゼロだと思いますが、こういう作業はやはりプログラムでやる方がイレギュラーなミスが出ないので良いと思います。バグは法則性を持っているのでランダムなミスより発見が容易です。


TextTreeは日本語の文字コードにShift-JISを使用していますが、gjots2ではこれが文字化けしてしまうので、UTF-8に変換する必要があります。
そのために nkf というソフトウェアを使っています。
これもSynaptic Package Managerからインストールできます。



以下、スクリプト。

ttree2gjots.sh

#!/bin/sh

# help switching from TextTree (http://www.vector.co.jp/soft/winnt/personal/se366853.html) to gjots2.
# Specify the root directory for TextTree, and gjots2 file is out.
# can specify extensions.  quote by " " for multiple.
# default is "txt".
# extension is case sensitive.
# option -d: directories appear before files.
# otherwise, files come above.
# to save into a file, use " > filepath " 

# depends on.
#   nkf

# systax.
#   ttree2gjots.sh [-d] <ttree root> [extensions (can be multiple)]

# example
#   ttree2gjots.sh root/ "txt csv TXT CSV" > ttree.gjots

# author. Kohta Mori
# date. 05/22/2010

######



# get options
d=N
while getopts d option
do
    case "$option" in
    d)
        d=Y
        shift  # shift up argument index to fill the part for the option
        ;;
    esac   
done




# check existence of the root directory
if [ -d "$1" ]
then
    echo #"directory $1 found"
    # do nothing
else
    echo "directory $1 not found"
    exit
fi


# set extensions
if [ $# -eq 2 ]
then
    ext="$2"
else
    ext="txt"
fi




# functions ---------------------------- #
d_routine()
{
    # method to handle all directories within a directory
    # $1: (parent) directory name
   
    for dr in "$1"/*/  # for all sub-directories
    do
        if [ -d "$dr" ]
        then
            # this if clause if necessary
            # to deal with empty folders
           
            echo \\NewEntry
           
            # remove "/" at the end
            l=${#dr}
            t=`expr $l - 1`
            tmp=`echo $dr | cut -c 1-$t`
            echo ${tmp##*/}
           
            echo \\NewFolder   
           
            Folder "$dr"
           
            echo \\EndFolder
        fi
    done

}


f_routine()
{
    # method to handle all files within a directory
    # $1: (parent) directory name
   
    for e in $ext
    do
        for f in "$1"/*.$e
        do
            if [ -f "$f" ]
            then
                fname=${f##*/}  # remove parts before /
                fname=${fname%.*} # remove extension
               
                echo \\NewEntry
                echo "$fname"
                echo "  "
               
                # the contents of the file
                nkf -w "$f" 
                # this reads and outputs the contents of the file
                # in UTF-8.
                echo " "
                # just to add line break at the end of each file
                # error occurs when .... \EndFolder
               
                # end of the file                   
               
            fi
        done
    done   

}



Folder()
{
    # the sub-routine for a folder
    # $1: the path (relative to the current directory) of the folder
   
    # for debugging (to avoid infinite loops) #
    #if [ -d "$1" ]
    #then
    #    echo
    #else
    #    echo "directory $1 not found"
    #    exit
    #fi
    # --------------------------------------- #
 
   
    if [ "$d" = Y ]
    then
       # directories first
       d_routine "$1"
       f_routine "$1"
    else
        # files first
       f_routine "$1"
       d_routine "$1"
    fi
   
   

   
}

# end of functions ---------------------- #



# let's get started! #
Folder "$1"










あるディレクトリ内の特定の拡張子のファイルをmp3に変換するシェルスクリプト。シェルの勉強に書いた。

syntax:
 $ sh dir2mp3 <target directory> <input extension> [ffmpeg options]

ffmpegがインストールされていて、libmp3lameコーデックがencodaleであることが前提(参考)。
1行目は環境に応じて変える。
一応 dir2mp3.sh という名前をつけたけど名前は何でもいい。
実質的には最後の6行だけでいい。


#!/bin/sh

# convert files in a directory into mp3.
# does not look for files in sub-directories.
# depends on ffmpeg.
# author: kohta
# date: 05/19/2010

# arguments
#   $1: target directory (can be relative)
#   $2: input extension (can be video)
#   $3: (optional) options to cast to ffmpeg (please quote by " ")

# example
#   dir2mp3.sh ~/Music m4a "-y -ac 2 -ab 128k"

# hint
#   add "-y" to the third argument to avoid overwrite queries


echo "This is" $0 "..."
echo "syntax:"
echo "  sh" $0 "<target directory> <input extension> [ffmpeg options]"



if [ $# -eq 2 ]; then
    echo "target directory:" $1
    echo "input extension: " $2
elif [ $# -eq 3 ]; then
    echo "target directory:" $1
    echo "input extension: " $2
    echo "ffmpeg options:  " $3
else
    echo "need at least 2 arguments: <target directory> and <input extension>"
    exit
fi



for file in $1/*.$2
do
    echo "converting" $file "to mp3 with options" $3 "..."
    ffmpeg -i "$file" -acodec libmp3lame $3 "${file%$2}mp3"
    echo "done."
done







Calender
10 2018/11 12
S M T W T F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
Search in This Blog
Latest Comments
[03/30 川内のばば山田]
[03/30 川内のばば山田]
[08/06 Aterarie]
[07/05 Agazoger]
[07/01 Thomaskina]
Oldest Posts
Latest Trackbacks
フリーエリア

Barcode
Access Analysis
Powerd by NINJAブログ / Designed by SUSH
Copyright © Yaleで、遊んで学ぶ日々。 All Rights Reserved.
忍者ブログ [PR]