-+- マニュアル -+- 
 
0.0 序文

    ようこそ、xyzshの世界へ。

    xyzshはインタラクティブシェルでもありテキスト処理ツールでもあるスクリプト言語です。

    PerlやRubyのようなテキスト処理コマンドを含み、オブジェクト指向プログラミングも行えます。

    もちろん、インタラクティブシェルではコマンド名やオブジェクト名のコマンドライン補完も行われます。

    何度も使わないような書き捨ての処理を短時間で、(時には対話的に)書く用途に向いていると思います。

    対象とするユーザーとしては、bashやperl, python, ruby, sed, awkなど一通りマスターしたけれども
    「もっと何か無いかな?」 と思っておられる方です。
    初心者の方は最初にbashやperlなどを学んだほうがいいと思います。
    (大抵のシステムではそちらがインストールされているので)

    使用に当たっては、このプログラムによって被る結果には自分で責任を持つことをお願いします。

    このプログラムのラインセンスはMITラインセンスです。自由に再配布でき書き換えることもできます。
    詳しくはwikipediaなどでMITラインセンスについて調べてください。ここでは述べません。

    ネット上の配布元としては

    安定板 http://sourceforge.jp/projects/xyzsh
    開発版 http://sourceforge.jp/projects/xyzsh/scm/git/xyzsh/

    にあります。

    gitを使えば、あなたもxyzshの開発者となることができます。
    コマンドの追加やバグの修正など、改良結果のコミットは歓迎させていただきます。
    forkして新規プロジェクトとして開発を行っても全然構いません。

1.0 構文

    (オブジェクト::)*コマンド (引数|-オプション|ブロック) (引数|-オプション|ブロック) ...

    (例)
    > ls
    > ls -al
    > ls | sub -global a (|uc)
    > sys::dmesg | sub -global . | less

    コマンド名や引数には英数字以外にも記号も使うことができます。

    xyzshで使われる特殊文字を使いたい場合は次のクォートを使ってください。

1.1 クォート

    xyzshで使われる特殊な文字を普通の文字列として使いたい場合、クォートする必要があります。

    クォートの方法は

    1. シングルクォートで囲む  (例) 'string'
    2. ダブルクォートで囲む (例) "string"
    3. 特殊文字の前にクォートを付ける (例) \;
    4. %q(), %Q()などのクォート

    の4つがあります。

    クォートとクォートの関係は排他的で、あるクォートの中では他のクォートは意味を失います。 
    
    > print "'string'"
    'string'

    > print '"string"'
    "string"

    > print '\\'
    \\

    ただしダブルクォートの中ではエスケープシーケンスやクォートは意味を持ちます。

    > print "\""
    "

    > print "\\"
    \

    シングルクォートの中ではエスケープシーケンスやクォートは意味を持ちません。

    > print '\''
    error

    > print '\\'
    \\

    クォートの後に特定の英字を置くことでコントロールキャラクタがコマンドラインに埋め込まれます。(エスケープシーケンス)

    \n 改行
    \r キャリッジリターン
    \a ベル

    > print "Hello World\nHello World\nHello World\n"
    Hello World
    Hello World
    Hello World

    これはシングルクォート内では展開されません。

    > print 'Hello World\nHello World\nHello World\n'
    Hello World\nHello World\nHello World\n

    %q(), %Q()によるクォートは以下のように使います。

    > sys::ruby -e %q<print "'Hello World'\n">
    'Hello World'

    > sys::ruby -e %q!print "'Hello World'\n"!
    'Hello World'

    > print %q(Hello World\n)
    Hello World\n

    > print %Q/Hello World\n/
    Hello World

    %Qの場合はエスケープシーケンスや変数が展開されます。

1.2 パイプとコンテキストパイプ
    
    コマンドはパイプで繋げることができます。その場合、前のコマンドの出力が次のコマンドの入力となります。

    > ls | sub -global . X

    ls(カレントディレクトリのファイルの一覧を出力する) のファイル名のリストの出力がsub -global . X(全ての文字をXに変換する)の入力となり実行されます。

    > ls | less

    lsの出力がless(画面を制御してlsの出力を見やすいようにする)の入力となり実行される。

    > ls | ( | less; | sub -global . X )

    ()はサブシェルで複数の文を一つのコマンドとして扱えます。| lessはコンテキストパイプを使って入力を受け取っています。
    コンテキストパイプはコマンドによってブロック内で受け取れる入力が変わるパイプです。
    この場合(subshellの場合)はブロック内で前のコマンドの出力を受け取ることができます。
    よってlsの出力をlessが受け取って実行し、次にlsの出力がsub -global . Xで受け取られて標準出力に出力されます。

1.3 文の区切りと戻り値

    ; \n 普通の区切り
    || 前の文の戻り値が偽なら次の文を実行する
    && 前の文の戻り値が真なら次の文を実行する
    & 最後のコマンドが外部コマンドであれば、最後の外部コマンドをバックグラウンドで実行する

    > pwd; pwd
    /home/ab25cq
    /home/ab25cq

    > make && make install
    makeを実行して戻り値が真なら(makeが成功すれば)make installを実行する

    > make || raise "make error"
    makeを実行して戻り値が偽なら(makeが失敗すれば)エラーを起こす

    文の最初に!を付けることによって戻り値の真偽を反転することができます。

    > ! true
    return code is 1

    > ! false

1.4 オプション

    -から始まる引数は全てオプションとして扱われます。
    -から始まる引数をオプションとして扱いたくない場合はクォートしてください。

    > sub -global . X

    -globalはsubにオプションとして渡される

    > print "-aaa" | less

    -aaaはオプションとして扱われずにlessに渡せる

    >  echo -aaaa | less

    など外部コマンドに-から始まる文字列を渡す場合はクォートされてもされなくてもechoに文字列として渡されます。

1.5 基本的なコマンド

    if 内部コマンドは条件分岐を行います。

    if (一つ目の条件式) (一つ目の条件式が真なら実行されるブロック) (二つ目の条件式) (二つ目の条件式が真なら実行されるブロック),..., (全ての条件式が実行されなければ実行されるブロック)

    ifは単にブロックを見ているだけなのでelseやelifなどは好きに入れていただいても構いません。

    > var a | if(|= main\n) (print true\n) else (print false\n)

    変数aの出力がmain\nならtrueを表示、違うならfalseを表示。

    条件式内部コマンドには以下があります。

    -n 入力があるなら真
    -z 入力がないなら真
    -b ファイルが存在し、ブロックスペシャルファイルなら真
    -c ファイルが存在し、キャラクタスペシャルファイルなら真
    -d ファイルが存在し、ディレクトリなら真
    -f ファイルが存在し、通常ファイルなら真
    -h 
    -L ファイルが存在し、シンボリックファイルなら真
    -p ファイルが存在し、名前付きパイプであれば真
    -t
    -S ファイルが存在し、ソケットであれば真
    -g ファイルが存在し、set GIDされていれば真
    -k ファイルが存在し、stickyビットが立っていれば真
    -u ファイルが存在し、set SUIDされていれば真
    -r ファイルが存在し、読み取り可能であれば真
    -w ファイルが存在し、書き込み可能であれば真
    -x ファイルが存在し、実行可能であれば真
    -O ファイルが存在し、実効ユーザーIDによる所有であれば真
    -G ファイルが存在し、実効グループIDによる所有であれば真
    -e ファイルが存在すれば真
    -s ファイルが存在し、サイズが0より大きければ真
    =  入力が引数と等しければ真
    != 入力が引数と等しくなければ真
    -slt 入力が引数より文字列として小さければ真
    -sgt 入力が引数より文字列として大きければ真
    -sle 入力が引数より文字列として小さいか同じであれば真
    -sge 入力が引数より文字列として大きいか同じであれば真
    -eq 入力が引数より数値として同じであれば真
    -ne 入力が引数より数値として同じでなければ真
    -lt 入力が引数より数値として小さければ真
    -le 入力が引数より数値として小さいか同じであれば真
    -gt 入力が引数より数値として大きければ真
    -ge 入力が引数より数値として大きいか同じであれば真
    -nt ファイルが引数のファイルより新しければ真
    -ot ファイルが引数のファイルより古ければ真
    -efA ファイルが引数のファイルと同じi-nodeであれば真
    =~ 入力が引数の正規表現とマッチすれば真(ローカル変数のPREMATCHにマッチの前の部分、 MATCHにマッチした部分、POSTMATCHにマッチした後の部分, 1など数値の番号にグループ化にマッチした文字列が入ります)

    ifもパイプを繋げることも可能です。

    > var a | if(|= main\n) (print true\n) else (print false\n) | scan . | less

    出力されたtrue\nもしくはfalse\nを毎行一文字に変換してからlessで表示。

    while内部コマンドは条件式が真の間ループを続けます。

    > print 0 | var a; while(var a | -le 5) ( print $a; ++ a)
    012345
    
    これもパイプを繋げることができます。

    > print 0 | var a; while(var a | -le 5) (print $a; ++ a ) | pomch

    Control-cが押されるとsignal interruptエラーが起きて実行を停めます。このエラーはtry内部コマンドで受け取ることができます。

1.6 変数

    xyzshの変数には以下の3つがあります。

    1. 文字列、もしくは数値

        文字列1行分を格納します。文字列は数値としても扱われます。

        > ls | var a b c   

        lsの最初から3行目までが1行ずつa, b ,c に格納されます。

        変数を出力したい場合は

        > var a b c
        lsの1行目
        lsの2行目
        lsの3行目

        と出力することができます。この出力には改行を含みます。

        変数を参照したい場合は

        > print "$a $b $c" \n
        lsの1行目 lsの2行目 lsの3行目

        となります。この場合は改行を含みません。

    2. 動的配列

        全文を格納したい場合は

        > ls | ary a

        とします。lsの出力全てがaに格納されます。一つの行が一つの要素として格納されます。

        出力したい場合は

        > ary a

        とします。

        要素一つを出力したい場合は

        > ary -index 1 a

        です。

        変数を参照したい場合は

        > print $a

        とすると$aの各要素(各行)が一つの引数としてprintに渡されます。

         > print $a[0]

        とすると最初の一行がprintに渡されます。

    3. ハッシュテーブル

        ハッシュテーブルは奇数行がキー、偶数行がアイテムというテキストのイメージを格納します。

        > print "key1 item1 key2 item2" | split | hash a

        とすれば、ハッシュaのkey1にitem1がkey2にitem2が格納されます。

        全てを出力したい場合は

        > hash a
        key2
        item2
        key1
        item1

        となります。ハッシュテーブルの場合は格納された順番と出力の順番は一致しません。

        要素一つを出力したい場合は

        > hash -key key1 a
        item1

        です。

        変数を参照したい場合は

        > print $a[key1]

        とすると$aのキーkey1の要素がprintに渡されます。

    あと変数の種類にはローカル変数とグローバル変数(オブジェクトの属性)とがあります。

    変数を参照する場合、ローカル変数->カレントオブジェクトの属性->カレントオブジェクトの親の属性....

    と検索されます。カレントオブジェクトについては次章を読んでください。

    ローカル変数を作るには

    > ls | var -local a b c

    と-localオプションを使って作ってください。ローカル変数は

    1. スクリプトファイルのload時 2. メソッドが呼ばれたとき 3. クラスが呼ばれたとき

    に初期化されます。またコマンドラインではコマンドが実行されるたびにローカル変数は初期化されます。

    > ls | var -local a b c
    > var a b c
    not found variable

    > ls | var -local a b c ; var a b c

    は出力されます。

    変数は変数名で内容を出力することができます。

    > ls | var a b c
    > a
    AUTHORS
    > b
    LICENCES
    > c
    Makefile.in

    変数の展開時オプションはクォートされてしまいます。(オプションとして解釈されない)
    解釈させるためには$-varなどと$-で変数を参照します。

    > print "1234512345" | index -count 2 1
    5
    > print "-count" | var a
    > print "1234512345" | index $a 2 1
    invalid command using
    > print "1234512345" | index $-a 2 1
    5


1.7 オブジェクト指向

    xyzshのオブジェクト指向はファイルシステムのようなものだと思ってください。
    ディレクトリがオブジェクトでその中にどんどん他のオブジェクト(文字列や配列オブジェクトなど)を追加していくことができます。

    > object a       # カレントオブジェクトにobject aを作成する
    > a::run ( ls | ary A )      # lsの出力結果をオブジェクトaにAとして追加する
    > a::A
    lsの出力

    a::runはカレントオブジェクトをaとしてブロックを実行します。よってlsの出力結果は配列Aとしてaに追加されます。
    ではobject aはどこに追加されるのでしょうか?それはカレントオブジェクトです。初期値の場合はルートオブジェクトとなります。
    この場合はカレントオブジェクトにオブジェクトa(中には配列Aが入っている)が追加されました。
    カレントオブジェクトは

    > pwo

    で確認できます。

    カレントオブジェクトは

    > co オブジェクト名

    で変更できます。

    上の例で行くと

    > co a

    でカレントオブジェクトをaに変更できます。

    で、

    > A

    と実行すればlsの出力を得ることができます。(root::aがカレントオブジェクトなのでa::は必要なくなる)

    > self

    で現在のカレントオブジェクトに定義された属性の一覧を得ることができます。
    カレントオブジェクトの初期値はルートディレクトリですが、ルートオブジェクトでselfを実行するとxyzshの組み込みの内部コマンドや基本的な外部コマンドが定義されているのが分かると思います。
    オブジェクトの参照順はローカル変数->カレントオブジェクト->親のオブジェクト ... -> ルートオブジェクト

    となっているので、子供のオブジェクトがカレントオブジェクトでも、ルートオブジェクトにある内部コマンドは参照することができます。

    また全てのオブジェクトには

    run メソッド
    と
    showメソッド
    と
    selfオブジェクト (そのオブジェクト自身のリファレンス)
    と
    rootオブジェクト (ルートオブジェクトのリファレンス)
    と
    parentオブジェクト(親オブジェクトのリファレンス)

    を含みます。よって

    > co parent

    で親オブジェクトに移動することができます。

    定義したオブジェクトや配列などは

    > sweep オブジェクト

    で削除することができます。

1.8 関数(メソッド)

    関数はdefコマンドによって定義されます。defが実行されたカレントオブジェクトに関数が追加されます。

    > def fun ( print fun \n)
    > fun
    fun
    > self | egrep ^fun:
    fun: function

    関数に渡された引数はローカル変数のARGV配列に入っています。

    > def fun ( print $ARGV )
    > fun aaa bbb ccc
    aaa bbb ccc

    関数に渡されたオプションはローカル変数のOPTIONSハッシュテーブルに入っています。

    > def fun ( hash OPTIONS )
    > fun -abc -def
    -abc
    -abc
    -def
    -def

    defには-option-with-argumentオプションを取ることができ、

    > def fun -option-with-argument abc,def ( hash OPTIONS )

    とすれば、-option-with-argumentで設定された引数は次の引数を取るようになります。

    > fun -abc aaa -def bbb -ghi
    -abc
    aaa
    -def
    bbb
    -ghi
    -ghi

    引数で受けたオプションをまた別のコマンドに渡したい場合はuniqコマンドを使ってください。

    > def fun ( OPTIONS )
    > def fun -inherit ( inherit $$-(OPTIONS|uniq) )
    > fun -abc -def
    -abc
    -abc
    -def
    -def

1.9 クラス

    クラスは関数とほとんど同じで呼ばれると実行されます。
    
    クラスはclassコマンドで定義します。

    > class klass ( print aaa\n )
    > klass
    aaa

    > class klass ( ls | ary AAA )
    > object a
    > a::run klass

    オブジェクトaにAAA配列オブジェクトが追加される。

    もしmainという名前のオブジェクトがオブジェクトで定義されていたら、オブジェクトをコマンドとして呼び出した場合、そのmainというオブジェクトが実行されます。

    > object a ( def main ( print called \n ) )
    > a
    called

    関数との違いはvar, ary, hash, defなどのオブジェクトの生成の登録先が違います。

    > def Fun ( split -target "AAA BBB CCC" | var A B C )
    > def Klass ( split -target "DDD EEE FFF" | var D E F )
    > object a
    > a::run ( Fun )
    > a::A
    run time error
    xyzsh 1: [A] there is not this object
    > a::B
    run time error
    xyzsh 1: [B] there is not this object
    > a::C
    run time error
    xyzsh 1: [C] there is not this object
    > A
    AAA
    > B
    BBB
    > C
    CCC
    > a::run ( Klass )
    > a::D
    DDD
    > a::E
    EEE
    > a::F
    FFF

2.0 コマンド置換

    ブロックの出力をコマンドに貼付けます。

    > print $(ls)
    main.c
    sub.c

    $$()によるコマンド置換は各行を一つの引数として貼付けます。

    > def fun ( ary -size ARGV )

    > fun $$(print aaa\nbbb\nccc\n )
    3

    行の区切りは$$a(), $$m(), $$w()を使うことによってそれぞれ、ベル、CR、CRLFと変えることができます。

    > def fun ( ary -size ARGV )

    > fun $$a(print aaa bbb ccc | split -La)
    3

    > fun $$m(print aaa bbb ccc | split -Lm)
    3

    > fun $$w(print aaa bbb ccc | split -Lw)
    3

    オプションを展開したい場合は$-(), $$-()を使います。

    > print "1234512345" | index -count 2 1
    5
    > print "1234512345" | index $(print "-count") 2 1
    invalid command using
    > print "1234512345" | index $-(print "-count") 2 1
    5

2.1 例外

    tryコマンドは例外処理を扱えます。tryの第一ブロックでエラーが起きるとエラーが起きた時点で直ちに第二ブロックが実行されます。
    起こったエラーは第2ブロックのコンテキストパイプで得られるエラーメッセージで知ることができます。

    > try ( print ) catch ( |=~ "invalid command using" && print "get invalid command using" )

    raiseコマンドによってエラーを起こすことができます。

    > try ( make || raise "failed on make"; sudo make install) ( print make failed\n )

2.2 リファレンス

    refコマンドはリファレンスを扱うことができます。
    ref 変数名で、その変数のアドレスを出力できます。

    > ls | var a b c; ref a b c
    0x12345678
    0x23456789
    0x34567890

    逆に

    > print 0x12345678 | ref x

    として入力を受け取るとそのアドレスのオブジェクトをxにバインドすることができます。

    つまり

    > ls | var a b c; ref a b c | ref x y z

    とするとaとx, bとy,cとzは同じものとなります。

    アドレスはxyzshによって保護され不正なアドレスははじくようになっています。

2.3 外部コマンド

    外部コマンドは起動時にrehashされてsysオブジェクトの中に外部コマンドオブジェクトとして入れられます。
    rehash内部コマンドが実行されるたびにsysオブジェクトの中に新しく作られます。

    > sys::dmesg    # dmesg外部コマンドを実行

    ただし、lsなど使用頻度が高いコマンドについてはリファレンスによってルートオブジェクトに登録されています。

    よってlsなどはsys::を付けなくても実行できます。

    > ls    # sys::lsでなくても良い

    sys::を省略したい外部プログラムを追加するには~/.xyzsh/programにあるプログラム一覧にプログラム名を追加してください。その後rehashをすると追加されます。

    > print dmesg\n >> ~/.xyzsh/program
    > rehash
    > dmesg
   

2.4 サブシェル

    複数の文を一つのコマンドのように扱えることができます。

    (pwd; echo aaa ; print bbb\n) | less

    pwd, echo aaa, print bbb\nの出力が次のlessコマンドに渡される。

    コンテキストパイプには前のコマンドの出力が入っています。

    pwd | ( | less; | less; | sub -global . (|uc))

    pwdの出力を2回lessして、最後に全ての文字を大文字にして出力する

2.5 コメント

    # から次の改行までがコメントとなります。

    > ls -al     # --> ファイルの一覧の出力

2.6 チルダ展開

    ほぼbashと同じ用法で使えます。

2.7 グロブ
    
    ほぼbashと同じ用法で使えます。glob(3)を使っています。

2.8 ヘアドキュメント

    ヘアドキュメントは改行を含む文字列を扱いたい場合に便利な用法です。

    > print <<<EOS
    aaaa
    bbbb
    cccc
    EOS | less

    <<<EOSの次の行から最初にEOSが来る行までが一つの文字列として扱われます。
    lessは
    aaaa
    bbbb
    cccc
    と改行を含む文字列を受け取れます。

    ただしbashのように

    print <<<EOS | less
    aaaa
    bbbb
    cccc
    EOS

    とは使えません。あしからず。

    ヘアドキュメントの中でも変数は展開できます。

    > ls | var a b c; 
    print <<<EOS
    $a
    $b
    $c
    EOS | less
    
    lessは
    $aの中身
    $bの中身
    $cの中身
    を受け取れます。

    変数を展開したくない場合は

    > print <<<'EOS'
    $a
    $b
    $c
    EOS | less

    とシングルクォートを使ってください

2.9 グローバルパイプ
    
    文の最後に|>をつけるとグローバルパイプへの書き込みとなります。

    > ls |>

    書き込んだグローバルパイプは、文の最初に|>をつけると読み込めます。

    > |> print
    main.c
    sub.c
    sub2.c
    
    > |> print
    main.c
    sub.c
    sub2.c

    追記は|>>です。

    > print aaa\n |>
    > print bbb\n |>>
    > |> print
    aaa
    bbb

3.0 行コンテキストパイプ

    コンテキストパイプの次に数字を指定すると読み込む行数を指定できます。

    > print aaa bbb ccc | split | (|1 print)
    aaa

    > print aaa bbb ccc | split | (|2 print)
    aaa
    bbb

    > print aaa bbb ccc | split | (|1 print; |1print; |1print; |1print)
    aaa
    bbb
    ccc
    return code is 262

    > print aaa bbb ccc | split | (|-1 print )
    aaa
    bbb
    ccc

    > print aaa bbb ccc | split | (|-2 print )
    aaa
    bbb

    > print aaa bbb ccc | split | (|-2 print; |-1 print )
    aaa
    bbb
    ccc

3.1 リダイレクト
    
    リダイレクトには>,>>,<が使えます。
    
    > ls | write AAA
    > cat <AAA
    main.c sub.c fix.c

3.2 エラー出力

    エラー出力をファイルに書き込む場合は"write"コマンドと"-error"オプションを使ってください。

    > ./output-error-program 
    data
    error-data

    > ./output-error-program | write -error data-from-error
    data

    > ./output-error-program | write data
    error-data

    > ./output-error-program | write -error data-from-error > /dev/null

    エラー出力を読み込むには"print"コマンドと"-read-from-error"オプションを使ってください

    > ./output-error-program | print -read-from-error
    error-data

    > ./output-error-program | (|print -read-from-error; | print ) | less
    error-data
    data

    > ./output-error-program | (|print -read-from-error | less; | print | less)
    error-data
    data

3.3 複数行のテキストの取り扱い

    xyzshで複数行のテキストを一つの変数に入力したい場合は-Laオプションを使ってください。
    \aが行の区切りとして扱われ、結果\n,\r\n,\rなどを単なるテキストとして処理でき、複数行のテキストを扱えます。
    少し複雑なコードとなりますがpコマンドでデバッグすれば、理解できるかと思います。

3.4 コマンドライン補完

    コマンドライン補完にはreadlineを使っているので、ほぼbashと同じように使うことができます。

    ユーザー定義の補完も作ることができcompletion.xyzshで内部コマンドのユーザー定義補完が定義されています。
    ユーザー定義の補完はroot::complにオブジェクトとして登録されています。

    C-xでマクロによるコマンドの出力結果をコマンドラインに貼付けることもできます。~/.xyzsh/macroを修正してください。

    括弧の対応のチェックには~/.inputrcにset blink-matching-paren onを書いておいてください。

    rlオブジェクトを使って補完のプログラム中にreadlineを操作できます。rl::helpを見てください。

3.5 ヘルプ

    help コマンド名

    でコマンドの使い方を見ることができます。各コマンドのオプションなどはそちらで調べてください。

3.6 C拡張ライブラリ

    C拡張ライブラリはload -dynamic-libraryを使って呼び出せます。サーチパスは/usr/local/lib/xyzsh/"ファイル名"(xyzshをインストールしたディレクトリ/lib/xyzsh/"ファイル名")を探して無いなら、~/.xyzsh/lib/"ファイル名"を探し、それでもないなら、"ファイル名(絶対パス、または相対パス)"を探します。拡張子は省略してはいけません。
    作り方について。migemoがC拡張ライブラリとなってます。詳しくはsrc/ext/migemo.cを見てください。dl_initとdl_finalを定義する必要があります。dl_initはload -dynamic-libraryをするときに呼ばれます。dl_finalはxyzshが終了するときに呼ばれます。拡張ライブラリのコンパイルは

    gcc -shared src/ext/migemo.c -o src/ext/migemo.so -lmigemo -lxyzsh $(LIBS) $(CFLAGS)

    などとすれば良いです。$(LIBS)と$(CFLAGS)は自分で定義する必要があります。

    拡張ライブラリと同じ名前 + .xyzshのソースファイルはload時に自動的に読み込まれます。ヘルプや補完などをそこに書くことができます。

3.7 xyzshの組み込みについて

    xyzshのメモリ管理について。xyzshはGCとスタックとmalloc&freeの3つのオブジェクトのメモリ管理を行なってます。しかし、以下の制限があります。
    GCで作り出されるオブジェクトはマークをさせるためにgRootObjectかgXyzshObjectから辿れるようにしなければなりません。(GCで管理されてgRootObjectかgXyzshObjectから辿れるコンテナオブジェクトに格納される必要がある)。でなければ、sweepで消されてしまいます。sweepは一定回数コードを実行すると自動的に実行されます。
    GCで作り出したコンテナオブジェクトにはGCで管理されるオブジェクトしか格納できません。同じようにスタックで作り出したコンテナオブジェクトにはスタックで管理されるオブジェクトを、MALLOCで作り出されるコンテナオブジェクトにはMALLOCで管理されるオブジェクトを格納してください。
    ユーザーによって定義される外部オブジェクト(EXTOBJ)の構造体内のオブジェクトではmallocによるオブジェクトの管理を行なってください。構造体内のオブジェクトをGCで管理を行なってmMarkFunでそのオブジェクトをマークしてもGCのオブジェクトのsweep順によっては正しく動作しません。セグメンテーションフォルトが起こる可能性もあります。ただし、blockオブジェクトはmallocによって管理できないので、blockオブジェクトは手動でマークしてください。stringオブジェクトもGCによって管理できるはずです。


-+- コマンド -+- 
 
--------------------------------------------------------------------------------
!= 引数

入力が引数と等しくなければ真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
* 数値

パイプのデータを数値としてみて引数の数値を乗算する。

> print 3 | * 3
9

--------------------------------------------------------------------------------
+ 数値

パイプのデータを数値としてみて引数の数値を加算する。

> print 3 | + 1 
4

--------------------------------------------------------------------------------
++ 変数名

引数の変数名をもつ変数がvarなら、数値としてみて+1する。

> print 1 | + 1 | var I
> print $I\n
2
> ++ I
> print $I\n
3
> I
3

--------------------------------------------------------------------------------
- 数値

パイプのデータを数値としてみて引数の数値を減算する。

> print 3 | - 1
2

--------------------------------------------------------------------------------
-- 変数名

引数の変数名をもつ変数がvarなら、数値としてみてー1する。

> print 1 | + 1 | var I
> I
2
> -- I
> I
1

--------------------------------------------------------------------------------
-G

ファイルが存在し、実効グループIDによる所有であれば真

--------------------------------------------------------------------------------
-L 

ファイルが存在し、シンボリックファイルなら真

--------------------------------------------------------------------------------
-O

ファイルが存在し、実効ユーザーIDによる所有であれば真

--------------------------------------------------------------------------------
-S

ファイルが存在し、ソケットであれば真

--------------------------------------------------------------------------------
-b 

ファイルが存在し、ブロックスペシャルファイルなら真

--------------------------------------------------------------------------------
-c 

ファイルが存在し、キャラクタスペシャルファイルなら真

--------------------------------------------------------------------------------
-d 

ファイルが存在し、ディレクトリなら真

--------------------------------------------------------------------------------
-e

ファイルが存在すれば真

--------------------------------------------------------------------------------
-ef 引数

ファイルが引数のファイルと同じi-nodeであれば真

--------------------------------------------------------------------------------
-eq 引数

入力が引数より数値として同じであれば真

--------------------------------------------------------------------------------
-f

ファイルが存在し、通常ファイルなら真

--------------------------------------------------------------------------------
-g

ファイルが存在し、set GIDされていれば真

--------------------------------------------------------------------------------
-ge 引数

入力が引数より数値として大きいか同じであれば真

--------------------------------------------------------------------------------
-gt 引数

入力が引数より数値として大きければ真

--------------------------------------------------------------------------------
-h 

なし

--------------------------------------------------------------------------------
-k

ファイルが存在し、stickyビットが立っていれば真

--------------------------------------------------------------------------------
-le 引数

入力が引数より数値として小さいか同じであれば真

--------------------------------------------------------------------------------
-lt 引数

入力が引数より数値として小さければ真

--------------------------------------------------------------------------------
-n 

入力があるなら真

--------------------------------------------------------------------------------
-ne 引数

入力が引数より数値として同じでなければ真

--------------------------------------------------------------------------------
-nt 引数

ファイルが引数のファイルより新しければ真

--------------------------------------------------------------------------------
-ot 引数

ファイルが引数のファイルより古ければ真

--------------------------------------------------------------------------------
-p 

ファイルが存在し、名前付きパイプであれば真

--------------------------------------------------------------------------------
-r

ファイルが存在し、読み取り可能であれば真

--------------------------------------------------------------------------------
-s

ファイルが存在し、サイズが0より大きければ真

--------------------------------------------------------------------------------
-sge 引数

入力が引数より文字列として大きいか同じであれば真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
-sgt 引数

入力が引数より文字列として大きければ真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
-sle 引数

入力が引数より文字列として小さいか同じであれば真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
-slt 引数

入力が引数より文字列として小さければ真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
-t

なし

--------------------------------------------------------------------------------
-u

ファイルが存在し、set SUIDされていれば真

--------------------------------------------------------------------------------
-w

ファイルが存在し、書き込み可能であれば真

--------------------------------------------------------------------------------
-x

ファイルが存在し、実行可能であれば真

--------------------------------------------------------------------------------
-z 

入力がないなら真

--------------------------------------------------------------------------------
/ 数値

パイプのデータを数値としてみて引数の数値を除算する。

> print 1 | / 2
0
> print 5 | / 2
2
> print 5 | / 0
run time error
xyzsh 1: [/] zero div
return code is 8192

--------------------------------------------------------------------------------
= 引数

入力が引数と等しければ真

-ignore-case 大文字と小文字を区別しない

--------------------------------------------------------------------------------
=~ 正規表現

入力が引数の正規表現とマッチすれば真(グローバル変数のPREMATCHにマッチの前の部分、 MATCH, 0にマッチした部分、POSTMATCHにマッチした後の部分, LAST_MATCHに最後にマッチした部分, 1..9の数値の番号にグループ化にマッチした文字列, MATCH_NUMBERにマッチした文字列の数が入ります)

-offsets マッチした位置(インデックス)の始点と終点を出力する(グループ化された文字列も含む)
-verbose マッチした位置(インデックス)を出力する
-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abcdefghijklmn | =~ e
> PREMATCH
abcd
> MATCH
e
> POSTMATCH
fghijklmn

> print abcdefghijklmn | =~ -verbose e
4

> print abcdefghijklmn | =~ z
return code is 4089

> print aaabbbcccdddeee | =~ '^(...)...(...)'
> PREMATCH

> MATCH
aaabbbbccc
> POSTMATCH
dddeee
> 1
aaa
> 2
ccc
> LAST_MATCH
ccc
> MATCH_NUMBER
3

> print aaabbbcccdddeee | =~ '^(...)...(...)' -offsets
0       # all matching offsets
9
0       # group 1 matching offsets
3
6       # group 2 matching offsets
9

--------------------------------------------------------------------------------
abs

パイプのデータを数値としてみて絶対値を出力する。

> print 2 | abs
2
> print -2 | abs
2

--------------------------------------------------------------------------------
add 文字列

文字列をパイプに追加するフィルター。

-index 数値 数値の位置に文字列を追加する
-number 数値 数値の位置に文字列を追加する
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print aaa | add X | add X | add X | pomch
aaaXXX
> print abcdefghi | add -index 1 XXX | pomch
aXXXbcdefghi

--------------------------------------------------------------------------------
ary 変数名 変数名, ... , 変数名

フィルタとして使われた場合は変数にパイプのデータの内容を入力する。
フィルタとして使われなかった場合は配列の内容を出力する。

-new オブジェクトを生成してアドレスを出力する
-local ローカル変数として扱う
-index 数値 配列の内容を出力する場合、数値のインデックスのみ内容を出力する。
-insert 数値 数値の位置に配列の内容を追記する。配列が無い場合新規に配列を作成する。
-append 配列に追記する。
-size 配列の大きさを出力する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "AAA BBB CCC" | ary A
> ary A
AAA
BBB
CCC
> A
AAA
BBB
CCC

> ary A -index 0
AAA
> ary A -index 1
BBB
> ary A -index 2
CCC
> ary A -index -1
CCC
> ary A -index 3

> print $A[0]\n
AAA
> print $A[1]\n
BBB
> print $A[-1]\n
CCC
> print $A[5]\n

> split -target "DDD EEE FFF" | ary -append A
> A
AAA
BBB
CCC
DDD
EEE
FFF

> print "XXX" | ary -insert 1 A
> A
AAA
XXX
BBB
CCC
DDD
EEE
FFF

> print "ZZZ" | ary -insert -2 A
> A
AAA
XXX
BBB
CCC
DDD
EEE
ZZZ
FFF

> ary -size A
8

> split -target "AAA BBB CCC" | ary -new | ref X
> X
AAA
BBB
CCC

> split -La -target "AAA\nBBB CCC\nDDD EEE\nFFF" " "| ary -La X
> X
AAA
BBB
CCC
DDD
EEE
FFF

> ary X -index 0
AAA
BBB
> ary X -index 1
CCC
DDD

--------------------------------------------------------------------------------
block 数値

実行中の関数に渡されたブロックのソースを出力する。
数値が無ければ0が渡されたものとして処理される。

-run 渡されたブロックを実行する
-number 渡されたブロックの数を返す

> def fun ( block | pomch )
> fun ( times 3 ( pwd ) )
times 3 ( pwd )

> def fun ( block -run )
> fun ( times 3 ( pwd ) )
/Users/ab25cq
/Users/ab25cq
/Users/ab25cq

> def fun ( block -run 1 )
> fun ( pwd ) ( whoami ) ( sys::groups )
ab25cq

> def fun ( block -number )
> fun ( pwd ) ( whoami ) ( sys::groups )
3

--------------------------------------------------------------------------------
break

while, each, for, timesループを終了する

> split -target "aaa bbb ccc" | each ( | print; | if(| chomp | = bbb) ( break ))
aaa
bbb

--------------------------------------------------------------------------------
cd ディレクトリ

カレントディレクトリを引数のディレクトリに変更する。
引数のディレクトリが省略された場合はホームディレクトリに移動する。

> pwd
/Users/ab25cq
> mkdir abc
> cd abc
> pwd
/Users/ab25cq/abc

--------------------------------------------------------------------------------
chomp

パイプのデータの末尾が改行コードなら取り除く。もし、取り除く改行が無ければリターンコードは1を返す

> print ABC\n | chomp
ABC
> print ABC | chomp
ABC
return code is 1
> split -target "ABC DEF GHI" | each ( | chomp )
ABCDEFGHI

--------------------------------------------------------------------------------
chop

パイプのデータの末尾の一文字を取り除く。末尾の文字が\r\nなら2つの文字列を取り除く。もし、取り除く文字列が無ければリターンコードは1を返す

-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print ABC | chop
AB
> print ABC\n | chop
ABC
> print ABC\r\n | chop
ABC
> print あいうえお | chop -utf8
あいうえ

--------------------------------------------------------------------------------
class クラス名(ブロック)

ブロックをクラスとして登録する。ブロックが無くフィルタとして使われた場合はパイプから得たデータをクラスとして登録する。
フィルタとして使われずにクラス名だけがある場合はクラスのソースを出力する。

-inherit 同名のクラスを上書きする場合、前のクラスを親クラスとして扱う。新しいクラスの定義内ではinherit内部コマンドで親クラスを呼び出すことができる。
-option-with-argument 複数の引数(カンマ区切り) ある引数を文字列をともに取る引数として設定する。
-copy-stackframe スタックフレーム(ローカル変数の入れ物)を新しく作る際に現在のスタックフレームの内容をコピーします。

> class fun ( times 3 ( echo Hello ) )
> fun
Hello
Hello
Hello

> print "times 3 ( echo Hello )" | class fun 
> class
Hello
Hello
Hello

> class fun | pomch
times 3 ( echo Hello )

> class fun ( echo Hello )
> class fun -inherit ( inherit; echo Hello2; ) 
> fun
Hello
Hello2

> class klass -option-with-argument abc,def ( hash OPTIOINS ); klass -abc aaa -def bbb ccc
 -abc
 aaa
 -def
 bbb
 ccc
 ccc

関数との違いはvar, ary, hash, defなどのオブジェクトの生成の登録先が違います。

> def Fun ( split -target "AAA BBB CCC" | var A B C )
> def Klass ( split -target "DDD EEE FFF" | var D E F )
> object a
> a::run ( Fun )
> a::A
run time error
xyzsh 1: [A] there is not this object
> a::B
run time error
xyzsh 1: [B] there is not this object
> a::C
run time error
xyzsh 1: [C] there is not this object
> A
AAA
> B
BBB
> C
CCC
> a::run ( Klass )
> a::D
DDD
> a::E
EEE
> a::F
FFF

--------------------------------------------------------------------------------
co

カレントオブジェクトを変更する。

> pwo
root
> object obj
> co obj
> pwo
root:obj
> co parent
> pwo
root

--------------------------------------------------------------------------------
combine (ブロック) (ブロック) ... (ブロック)

各ブロックの出力を混ぜ合わせて出力する。

-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> combine ( print aaa\nbbb\nccc\nddd\neee\n ) ( print AAA\nBBB\nCCC\n )
aaa
AAA
bbb
BBB
ccc
CCC
ddd
eee

--------------------------------------------------------------------------------
completion (オブジェクト::)コマンド名 (ブロック)

ブロックがあった場合はユーザー定義の補完を定義する。ブロックの出力結果が補完の候補となる(LF区切り)
補完オブジェクトはroot::complにオブジェクトとして登録される
ARGVにはコマンド名と入力中の文字列が入っている
コンテキストパイプには入力中の行が入っている
コマンド名に__all__を使うとコマンド名が見つからなかった時は__all__が使われる
ブロックが無かった場合は定義された補完を実行して結果を返す。

-source ソースを表示する

> completion cd ( 
    | file_completion | each ( | =~ '/$' && | print )
    print ../\n
    hash COMPLETION_OPTIONS -key cd
)
> ls | each ( | chomp | -d && | print )
src
man
doc
> cd [TAB]
.. src man doc
> completion -source cd

    | file_completion | each ( | =~ '/$' && | print )
    print ../\n
    hash COMPLETION_OPTIONS -key cd

> completion cd
..

--------------------------------------------------------------------------------
count カウントする文字の集合

文字の個数を出力します。文字の集合の形式はtr(1)と同じです。

abc --> abc
a-c --> abc
0-3 --> 0123
^a --> a以外

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print aaabbbcccdddeeeff | count a-c
9
> print あいうえおaaabbbcccあいうえお | count -utf8 あい
4
> print aaabbbcccdddeeefff | count a-c
9

--------------------------------------------------------------------------------
def 関数名(ブロック)

ブロックを関数として登録する。ブロックが無くフィルタとして使われた場合はパイプから得たデータを関数として登録する。
フィルタとして使われずに関数名だけある場合は関数のソースを出力する。

-inherit 同名の関数を上書きする場合、前の関数を親関数として扱う。新しい関数の定義内ではinherit内部コマンドで親関数を呼び出すことができる。親関数には内部コマンドもなることができる。
-option-with-argument 複数の引数(カンマ区切り) ある引数を文字列をともに取る引数として設定する。
-copy-stackframr スタックフレーム(ローカル変数の入れ物)を新しく作る際に現在のスタックフレームの内容をコピーします。

> def fun ( times 3 ( echo Hello ) )
> fun
Hello
Hello
Hello

> print "times 3 ( echo Hello )" | def fun 
> fun
Hello
Hello
Hello

> def fun | pomch
times 3 ( echo Hello )

> def fun ( echo Hello )
> def fun -inherit ( inherit; echo Hello2; ) 
> fun
Hello
Hello2

> def fun -option-with-argument abc,def ( hash OPTIOINS )
> fun -abc aaa -def bbb ccc
 -abc
 aaa
 -def
 bbb
 ccc
 ccc

クラスとの違いはvar, ary, hash, defなどのオブジェクトの生成の登録先が違います。

> def Fun ( split -target "AAA BBB CCC" | var A B C )
> def Klass ( split -target "DDD EEE FFF" | var D E F )
> object a
> a::run ( Fun )
> a::A
run time error
xyzsh 1: [A] there is not this object
> a::B
run time error
xyzsh 1: [B] there is not this object
> a::C
run time error
xyzsh 1: [C] there is not this object
> A
AAA
> B
BBB
> C
CCC
> a::run ( Klass )
> a::D
DDD
> a::E
EEE
> a::F
FFF

--------------------------------------------------------------------------------
defined オブジェクト

オブジェクトが定義されていたら真を返す

> ls | var A B C
> if(defined A) ( print yes\n ) ( print no\n )
yes
> if(defined D) ( print yes\n ) ( print no\n )
no

--------------------------------------------------------------------------------
del インデックス

パイプの中のインデックスの位置の文字を一文字削除して残りを出力するフィルター。

-number 文字数 文字数分削除する
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print 0123456789 | del 1 | pomch
023456789
> print 0123456789 | del 1 -number 2 | pomch
03456789

--------------------------------------------------------------------------------
delete 削除する文字の集合

文字を削除するフィルター。文字の集合の形式はtr(1)と同じです。

abc --> abc
a-c --> abc
0-3 --> 0123
^a --> a以外

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abcdefghi | delete a-z ^b-c | pomch
bc
> print abcdefghi | delete a-c | pomch
defghi
> print abcdefghi | delete ^a-c | pomch
defghi
> print あいうえお | delete -utf8 ^あ | pomch
あ

--------------------------------------------------------------------------------
each (ブロック)

パイプで受け取った各行をコンテキストパイプとして受け取りブロックを実行する

戻り値: 入力文字列が無ければ262

-number 数値 数値行ずつ実行する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "01aaa 02bbb 03ccc 04ddd 05eee" | each ( | print )
01aaa
02bbb
03ccc
04ddd
05eee

> print "aaa\nbbb ccc\nddd eee" | split -La " " | each -La ( |chomp| less )
--- less ---
aaa
bbb
------------

--- less ---
ccc
ddd
------------

--- less ---
eee
------------

> split -target "01aaa 02bbb 03ccc 04ddd 05eee" | each -number 2 ( | join )
01aaa 02bbb
03ccc 04ddd
05eee

--------------------------------------------------------------------------------
errmsg

エラーメッセージを出力する。

> groups
run time error
xyzsh 1: [groups] command not found
return code is 127
> errmsg
xyzsh 1: [groups] command not found

--------------------------------------------------------------------------------
eval (ブロック|文字列)

ブロックか文字列を実行する。文字列の場合は解釈され実行される。
フィルターとして使われた場合は入力された文字列を実行する。

戻り値: フィルターとして使われた場合入力文字列が無ければ262

> eval "print Hello\n"
Hello

> print ls | var A; eval "$A -al"
output of "ls -al"

> print "ls -al" | eval
output of "ls -al"

> cat src/main.c | eval "| uc |less"
output of "cat src/main.c|uc"

--------------------------------------------------------------------------------
exit

xyzshを終了する

> vim help.xyzsh # will be pressed CTRL-Z
> jobs
[1] vim help.xyzsh (pgrp: 46302)
> exit
run time error
xyzsh 1: [exit] jobs exist
return code is 8192
> exit -force

-force サスペンドされているジョブが残っていても強制的に終了する

--------------------------------------------------------------------------------
export 環境変数名 環境変数名2, ...., 環境変数名X

フィルタとして使われた場合パイプから各行を一つずつ受け取り、環境変数に代入していく。
フィルタとして使われなかった場合、環境変数の内容を出力する。

-shift フィルタとして使われた場合、パイプのデータから変数にバインドしたアドレスの残りを出力する。
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> export PATH
/bin:/usr/bin
> print $PATH:/usr/local/bin | export PATH
> export PATH
/bin:/usr/bin:/usr/local/bin
> split -target "AAA BBB CCC" | export A B -shift
CCC
> export A
AAA
> export B
BBB
> print $A\n
AAA
> print $B\n
BBB

--------------------------------------------------------------------------------
false

戻り値、偽を返す

>if(false) ( print yes\n ) else ( print no\n)
no

--------------------------------------------------------------------------------
fg ジョブ番号

サスペンドしたジョブをフォアグランドにもってくる

--------------------------------------------------------------------------------
for (変数名) in 引数の値1 引数の値2 ... (ブロック1)

ブロック1を毎回、引数の値がある限り、値を引数に代入して実行する。
ex)
> for i in a b c ( print $i \n )
a
b
c
> for i in $$(seq 1 3) ( print $i \n )
1
2
3

--------------------------------------------------------------------------------
fselector

ファイルを選択して出力させる

up key or C-p --> カーソルを上げる
down key or C-n --> カーソルを下げる
left key or C-b --> カーソルを左にする
right key or C-f --> カーソルを右にする
C-l --> スクリーンをリフレッシュする
\ --> ルートディレクトリに移動する
C-h or Backcpace --> 親ディレクトリに移動する

TAB key or 'w' --> 決定
q or C-c or Escape C-g --> キャンセル

-multiple 複数のファイルの選択を許す。スペースで選択する

--------------------------------------------------------------------------------
funinfo

実行中の関数もしくはクラスの情報を得る

> funinfo
run time error
xyzsh 1: [funinfo] invalid command using
return code is 8192
> def fun ( funinfo )
> fun
source name: xyzsh
source line: 1
run nest level: 2
current object: root
reciever object: root
command name: fun

--------------------------------------------------------------------------------
gcinfo

xyzshでメモリ管理に使われているガベージコレクションの使用状況を出力する

> gcinfo
free objects 3902
used objects 4285
all object number 8192
slot size 64
pool size 128

--------------------------------------------------------------------------------
hash 変数名 変数名, ... , 変数名

フィルタとして使われた場合は変数にパイプのデータの内容を入力する。
データは
1行目 ハッシュのキー
2行目 ハッシュのアイテム
3行目 ハッシュのキー
.
.
.
奇数行 ハッシュのキー
偶数行 ハッシュのアイテム
として格納される。
フィルタとして使われなかった場合はハッシュの内容を上の様に出力する。

-new オブジェクトを生成してアドレスを出力する
-local ローカル変数として扱う
-append フィルタとして使われた場合ハッシュを追記する。ハッシュが無い場合新規に作成する。
-size ハッシュのサイズを出力する
-key キー フィルタとして使われなかった場合ハッシュの内容をキーで渡されたキーのアイテムのみ出力する。
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "key1 item1 key2 item2 key3 item3" | hash A
> hash A
key3
item3
key2
item2
key1
item1

> print $A[key1]\n
item1
> hash A -key key1
item1
> print $A[key4]\n

> hash A -key key4

> hash A -key key2
item2

> A | each -number 2 ( | lines 0 )
key1
key2
key3

> A | each -number 2 ( | lines 1 )
item1
item2
item3

> hash A -size
3

> print key4\nitem4 | hash -append A
> A
key4
item4
key3
item3
key2
item2
key1
item1

--------------------------------------------------------------------------------
help コマンド名

ヘルプを表示する。コマンド名が無ければマニュアルと全てのコマンドのヘルプを表示する。

> help [TAB]
all commands are deplayed

> help cd | less
runned viewer with help of cd 

--------------------------------------------------------------------------------
if (条件式1) (ブロック1) (条件式2) (ブロック2) ... (条件式x) (ブロックx) (ブロック)

条件式が真ならば対応するブロックを実行する。もし全部の条件式が偽なら最後のブロックを実行する

> if(false) ( print 1\n ) elif(false) ( print 2\n ) else if (false ) ( print 3\n ) elsif (false) ( print 4\n) else ( print 5\n )
5

> ls | each ( | if(| chomp | -d) ( print found a directory\n ) )
found a directory
found a directory
found a directory

> split -target "aaaaa bbb cccccc ddd e" | each ( | if(|chomp|=~ ...) ( | print ))
bbb

--------------------------------------------------------------------------------
index 文字列

パイプから文字列を検索して見つかったインデックスを返すフィルター。

-regex 正規表現で検索する
-quiet 見つかった位置を出力しない。戻り値のみ設定する
-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-number 数値 文字列の検索を開始する位置を設定する
-count 数値 検索する回数を設定する
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print あいうえお | index -utf8 う
3
> print abcabcabc | index c
2
> print abcabcabc | index -number 6 c
8
> print abcabcabc | index -count 2 c
5
> print abcabcabc | index -regex '..c'
0
> print abcabcabc | index -ignore-case BC
1

--------------------------------------------------------------------------------
inherit 引数|オプション|ブロック

親クラス、親関数、親内部関数を呼び出す。

> def fun ( echo Hello )
> def fun -inherit ( echo Hello2; inherit )
> fun
Hello2
Hello

--------------------------------------------------------------------------------
jobs

サスペンドしたジョブの一覧を出力する

戻り値: ジョブが無ければ1

> vim help.xyzsh # will be pressed CTRL-Z
> jobs
[1] vim help.xyzsh (pgrp: 46302)
> fg

--------------------------------------------------------------------------------
join (区切り文字。省略時はスペースとなる)

配列(複数行)をつなげて一つの行とする

戻り値: 入力文字列が無ければ262

-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> print "aaa bbb ccc" | split | join 
aaa bbb cccc

> print "aaa bbb ccc" | split | join +
aaa+bbb+ccc

> ls | join ,
AUTHORS,CHANGELOG,LICENSE,Makefile,Makefile.in,README,README.ja,USAGE,USAGE.ja,a.xyzsh,aaa,bbb,ccc,completion.xyzsh,config.h,config.h.in,configure,configure.in,ddd,eee,help.xyzsh,install.sh,libxyzsh.1.7.1.dylib,libxyzsh.1.dylib,libxyzsh.dylib,man,read_history.xyzsh,src,xyzsh,xyzsh.dSYM,xyzsh.xyzsh

> print "aaa\nbbb ccc\nddd eee" | split -La " " | join -La +
aaa
bbb+ccc
ddd+eee

--------------------------------------------------------------------------------
jump

ジャンプメニューを表示する。xyzsh.xyzshで定義されたユーザー関数。~/.xyzsh/jumpにジャンプ先のディレクトリは書かれている。

> cat ~/.xyzsh/jump
/etc/
/var/log/

> jump
/etc/
/var/log

--------------------------------------------------------------------------------
kanjicode

現在の漢字コードを表示する。

> kanjicode   # default of xyzsh kanjicode is byte
byte
> kanjicode -utf8  # sett
> kanjicode
utf8

-byte バイトに設定する
-sjis sjisに設定する
-eucjp eucjpに設定する
-utf8 utf8に設定する

--------------------------------------------------------------------------------
lc 

大文字を小文字に変換するフィルター。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print ABCDEFG | lc
abcdefg

> print あいうえおABCかきくけこ | lc -utf8
あいうえおabcかきくけこ

--------------------------------------------------------------------------------
length

文字列の文字数を返すフィルター。

戻り値: 入力文字列が無ければ262

-byte バイトコードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する
-utf8 UTF8コードとして処理する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する
-line-num 改行数を出力する

> print abc| length
3
> print abc\n | length
4
> print あいうえお | length -byte
15
> print あいうえお | length -utf8
5
> print abc\ndef\n | length -line-num
2
> print abc\ndef | length -line-num
1
> split -target "abc def ghi" | each ( | chomp | length )
3
3
3

--------------------------------------------------------------------------------
lines 行 (ブロック) 行 (ブロック), ..., 行 (ブロック)

パイプから行を取り出しそれをコンテキストパイプとしてブロックを実行する。
ブロック数が行の数よりも少ないと、(|print)があるとみなされる。(そのまま出力する)
行には行番号と 
行1..行2 
の範囲指定が使える。行は0から始まり、-1以下は末尾から数えるものとする。
行1 > 行2の場合は逆順となる。

戻り値: 入力文字列が無ければ262

-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "aaa bbb ccc ddd eee" | lines 0 1 2
aaa
bbb
ccc

> split -target "aaa bbb ccc ddd eee" | lines 0 0 0
aaa
aaa
aaa

> split -target "aaa bbb ccc ddd eee" | lines -1 -2
eee
ddd

> split -target "aaa bbb ccc ddd eee" | lines 4..0
eee
ddd
ccc
bbb
aaa

> split -target "aaa bbb ccc ddd eee" | lines -1..0
eee
ddd
ccc
bbb
aaa

> split -target "aaa bbb ccc ddd eee" | lines 0..1 (| chomp | add XXX | pomch ) 2..-1 ( | uc )
aaaXXX
bbbXXX
CCC
DDD
EEE

> split -target "aaa bbb ccc ddd eee" | ( | lines 0..1 | join; | lines 2..-1 | join )
aaa bbb
ccc ddd eee

--------------------------------------------------------------------------------
load ファイル名 引数1 引数2 ... 引数X

スクリプトファイルを実行する。ローカル変数は初期化される。ARGVに引数が入っている。

-dynamic-library C言語による拡張ライブラリをロードする。サーチパスは/usr/local/lib/xyzsh/"ファイル名"(xyzshをインストールしたディレクトリ/lib/xyzsh/"ファイル名")を探して無いなら、~/lib/"ファイル名"を探す、それでもないなら、"ファイル名(絶対パス、または相対パス)"を探す。拡張子は省略してはならない。

> vim a.xyzsh
print Hello Script\n

> load a.xyzsh
Hello Script

> vim a.xyzsh
ARGV

> load a.xyzsh A B C
A
B
C

> load -dynamic-library [TAB]
migemo.so

> load -dynamic-library migemo.so

--------------------------------------------------------------------------------
lstrip

このフィルターはパイプのデータの前のスペース、タブ、改行コードを取り除きます。

> print "\n\naaa\nbbb\nccc\n\n" | lstrip
aaa
bbb
ccc

--------------------------------------------------------------------------------
menu

メニュー形式でコマンドを選択してコマンドを実行する。xyzsh.xyzshで定義されたユーザー関数。~/.xyzsh/menuに選択されるコマンドが書かれている。

> cat ~/.xyzsh/menu
pwd
ls
whoami
> menu

--------------------------------------------------------------------------------
mod 数値

パイプのデータを数値としてみて引数の数値で除算して余りを出力する。

> print 1 | mod 2
1

--------------------------------------------------------------------------------
msleep 数値

数値の時間だけ実行を止める。アニメーションが表示される。

> msleep 10
.oO.oO.oO.oO.oO.oO.oO.oO.oO

--------------------------------------------------------------------------------
object オブジェクト名1 オブジェクト名2, ..., オブジェクト名X (ブロック)

オブジェクトを作成する。ブロックがある場合はブロックで初期化される。

-new オブジェクトを生成して、アドレスを出力する。
-local ローカル変数として登録する。

> object a
> a::run ( split -target "AAA BBB CCC" | var A B C)
> a::A
AAA
> a::B
BBB
> a::C
CCC

> object a ( split -target "AAA BBB CCC" | var A B C)
> a::A
AAA
> a::run ( A )
AAA
> a::run ( var A )
AAA

> class Human ( | var Name Age; def show ( var Name Age | printf "name:%s\nage:%s\n" ) )
> object ab25cq ( split -target "ab25cq 35" | Human )
> ab25cq::Name
ab25cq
> ab25cq::Age
35
> ab25cq::show
name:ab25cq
age:35

--------------------------------------------------------------------------------
p

パイプの中身を覗く。ENTER KEYでパイプのデータの通過を許可する。ESC, qでエラーを起こし停止する。
デバッグ用のコマンドです。

戻り値: 入力文字列が無ければ262

-preserve-position カーソル位置とスクロールトップ位置を初期化しない
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> ls | p
run time error
xyzsh 1: [p] p: canceled
return code is 8192

> ls | p
AUTHORS
CHANGELOG
LICENSE
Makefile
Makefile.in
README
README.ja
USAGE
USAGE.ja
a.xyzsh
completion.xyzsh
config.h
config.h.in
configure
configure.in

--------------------------------------------------------------------------------
pomch

パイプの末尾に改行コードを追加する。

-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> print ABC | pomch
ABC
> print ABC\n | pomch
ABC
return code is 1
> split -target "ABC DEF GHI" | each ( |chomp | add XXX | pomch )
ABCXXX
DEFXXX
GHIXXX

--------------------------------------------------------------------------------
popd 

保存されたディレクトリスタックから一番最新のものをカレントディレクトリとして復帰する。

> pwd
/Users/ab25cq
> pushd .
> cd /
> pwd
/
> popd
> pwd
/Users/ab25cq

--------------------------------------------------------------------------------
pow 数値

パイプのデータを数値としてみて引数の数値でべき乗する。

> print 2  | pow 2

--------------------------------------------------------------------------------
print 文字列1 文字列2, ..., 文字列x

文字列を出力する
フィルターとして使われた場合は入力をそのまま出力する

戻り値: フィルターとして使われて入力文字列が無ければ16384

-error エラー出力に出力する
-read-from-error フィルターとして使われた場合のみ有効。エラー出力から入力を得る

> print "Hello World\n"
Hello World

> split -target "aaa bbb ccc" | each ( | print )
aaa
bbb
ccc

> print "" | print
return code is 16384

> cat main.c | while(|1 print |>) (|> join ""; )

> (print aaa\n; print -error error\n )
aaa
error

> vim a.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    fprintf(stdout, "OUTPUT\n");
    fprintf(stderr, "ERROR\n");
    exit(0);
}
> gcc a.c
> ./a.out | (|print -read-from-error | less; | less)

--------------------------------------------------------------------------------
printf

C言語のprinfのようにフォーマット文字を出力する。
ただしデータはパイプから各行を一つの文字列として受け取とる。

-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> ls | head -n 3
main.c
sub1.c
sub2.c

> ls | printf "%s,%s,%s\n"
main.c,sub1.c,sub2.c

> split -target "1 2 3 4 5" | printf "(%d,%d)\n(%d,%d,%d)"
(1,2)
(3,4,5)

> split -target "ABC\nDEF GHI\nJKL" " " -La | printf -La "(%s) (%s)"
(ABC
DEF) (GHI
JKL)

--------------------------------------------------------------------------------
prompt (ブロック)

インタラクティブシェルのプロンプトを設定する。ブロックの出力がプロンプトとして扱われる。

> prompt ( print "ab25cq's terminal > " )
ab25cq's terminal > 

--------------------------------------------------------------------------------
pushd ディレクトリ

引数のディレクトリをディレクトリスタックに保存する。

> pwd
/Users/ab25cq
> pushd .
> cd /
> pwd
/
> popd
> pwd
/Users/ab25cq

--------------------------------------------------------------------------------
pwo

カレントオブジェクトを表示する。
カレントオブジェクトとはクラス内で変数が作成される場合、その変数を属性として登録する登録先のオブジェクトのことである。

> pwo
root
> object obj
> co obj
> pwo
root:obj
> co parent
> pwo
root

--------------------------------------------------------------------------------
quote

記号をクォートするフィルター。

戻り値: 入力文字列が無ければ262

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print "abcdefghij%&$]" | quote | pomch
abcdefghij\%\&\$\]

--------------------------------------------------------------------------------
raise 文字列

エラーを起こす。文字列がエラーメッセージとなる。

> make && raise "make is failed"
run time error
xyzsh 1: [raise] make is failed
return code is 8192

> try (
    make || raise "make error"
    sudo make install || raise "sudo make install error"
) catch ( 
    | =~ "make error" && print "catch make error\n";
    | =~ "sudo make install error" && print "catch make install error\n"
)

--------------------------------------------------------------------------------
readline プロンプト | raedline プロンプト ( ブロック )

readlineを使って1文をユーザーの入力から読み込み、読み込んだ文字列を出力する。

ブロックがある場合はブロックの出力の一行が候補の補完を行なう。

-no-completion 補完を行わない

> readline -no-completion "Select yes or no > " |=~ ^y && print "selected yes"
Select yes or no > yes
selected yes

> readline "type command line > " | eval
type command line > pwd
/Users/ab25cq

> readline "Select yes or no > " ( split -target "yes no" ) |=~ ^y && print "selected yes"
Select yes or no > [TAB]
yes no

--------------------------------------------------------------------------------
ref 変数名 変数名, ..., 変数名

フィルタとして使われた場合はパイプの中に入った各行のアドレスを引数の変数名にバインド(代入)する。
フィルタとして使われなかった場合は、引数の変数名のアドレスを出力する。

-local ローカル変数として登録する
-shift フィルタとして使われた場合、パイプのデータから変数にバインドしたアドレスの残りを出力する。
-type フィルタとして使われた場合パイプから受け取ったアドレスの型を出力する。
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "aaa bbb ccc" | ary -new | ref X
> ref X
0x7fd73469c780
> X
aaa
bbb
ccc
> ary X
aaa
bbb
ccc

> ls | var A B C

> ref X A B C | ref -type
array
var
var
var

> ref -type X A B C
array
var
var
var

> ls | (|1 var -new; |1 var -new; |1 var -new )| ref -shift X
0x7f8c5de9f9c0
0x7f8c5de9f8c0

--------------------------------------------------------------------------------
rehash

環境変数PATHに登録されているディレクトリをサーチして実行可能なプログラムをroot::sysオブジェクトの中に外部プログラムオブジェクトとして格納する

> print $PATH:$HOME/bin | export PATH
> rehash

> groups
run time error
xyzsh 1: [groups] command not found
return code is 127
> sys::groups
staff com.apple.access_screensharing com.apple.sharepoint.group.1 everyone _appstore localaccounts _appserverusr admin _appserveradm _lpadmin _lpoperator _developer
> print groups\n >> ~/.xyzsh/program
> rehash
> groups
staff com.apple.access_screensharing com.apple.sharepoint.group.1 everyone _appstore localaccounts _appserverusr admin _appserveradm _lpadmin _lpoperator _developer

--------------------------------------------------------------------------------
return (リターンコード)

関数かクラスを実行中なら、途中で抜ける

> def fun ( print head\n; return 1; print tail)
> fun
head
return code is 1

--------------------------------------------------------------------------------
rindex 文字列

パイプから文字列を検索して見つかったインデックスを返すフィルター。
末尾から検索する。

-regex 正規表現で検索する
-quiet 見つかった位置を出力しない。戻り値のみ設定する
-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-number 数値 文字列の検索を開始する位置を設定する
-count 数値 検索する回数を設定する
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print あいうえおう | rindex -utf8 う
5
> print abcabcabc | rindex c
8
> print abcabcabc | index -number 6 c
5
> print abcabcabcabc | rindex -count 2 c
8
> print abcabcabc | rindex -ignore-case A
6
> print abcabcabc | rindex -regex '.b'
6

--------------------------------------------------------------------------------
rows インデックス (ブロック) インデックス (ブロック), ... , インデックス (ブロック)

パイプからインデックスの文字を取り出しそれをコンテキストパイプとしてブロックを実行する。
ブロック数が行の数よりも少ないと、(|print)があるとみなされる。(そのまま出力する)
インデックスには文字のインデックスと
インデックス1..インデックス2 
の範囲指定が使える。インデックスは0から始まり、-1以下は末尾から数えるものとする。
インデックス1 > インデックス2の場合は逆順となる。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print あいうえおかきくけこ | rows -utf8 0 0 0 | pomch
あああ
> print あいうえおかきくけこ | rows -utf8 1..2 | pomch
いう
> print あいうえおかきくけこ | rows -utf8 -1..0 | pomch
こけくきかおえういあ
> print あいうえおかきくけこ | rows -utf8 -1 -1 -1 | pomch
こここ
> print あいうえおかきくけこ | rows -utf8 1200 -100 -100 | pomch

> print abcdefghijk | rows 0 ( | uc ) 1..-1 ( | pomch )
Abcdefghijk

--------------------------------------------------------------------------------
rstrip

このフィルターはパイプのデータの後ろのスペース、タブ、改行コードを取り除きます。

> print "\n\naaa\nbbb\nccc\n\n" | rstrip

aaa
bbb
ccc

--------------------------------------------------------------------------------
run (クラス名|ブロック)

ブロックがある場合はメッセージが送られたオブジェクトをカレントオブジェクトとしてブロックを実行する。
クラス名がある場合は、メッセージが送られたオブエジェクトをカレントオブジェクトとしてクラスを実行する。
カレントオブジェクトとはクラス内で変数が作成される場合、その変数を属性として登録する登録先のオブジェクトのことである。

> object a
> a::run ( split -target "AAA BBB CCC" | var A B C)
> a::A
AAA
> a::B
BBB
> a::C
CCC

> object a ( split -target "AAA BBB CCC" | var A B C)
> a::A
AAA
> a::run ( A )
AAA
> a::run ( var A )
AAA

--------------------------------------------------------------------------------
scan 正規表現 (ブロック)

パイプから正規表現にマッチする文字列を何度も繰り返し探し、出力する。
ブロックがあれば、正規表現にマッチするたびにブロックが実行される。
ブロックのコンテキストパイプにはマッチした文字列が入っている。

マッチした回数はグローバル変数変数MATCH_COUNTに代入される。

ブロックでは以下のグローバル変数に特定の文字列が代入されている。

グループ化された文字列 1,2,..,9
マッチした文字列 MATCH, 0
マッチ以前の文字列 PREMATCH
マッチ以後の文字列 POSTMATCH
最後にマッチした文字列 LAST_MATCH
マッチした文字列の数 MATCH_NUMBER

-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> print abc | scan .
a
b
c
> print abcaaadefbbbghiccc | scan '(.)\1\1' | each ( | chomp | x 3 | pomch )
aaa
bbb
ccc
> print ABCDEFGHIJKABCDEFGHIJK  | scan -ignore-case a
A
A
> split -target "AAA BBB CCC DDD EEE" | scan -multi-line "BBB\nCCC"
BBB
CCC
> print abcaaadefbbbghiccc | scan "(.)\1\1" ( MATCH )
aaa
bbb
ccc
> print abcaaadefbbbghiccc | scan '(.)\1\1' ( 1|chomp; 1|chomp; 1 )
aaa
bbb
ccc
> print abcaaadefbbbghiccc | scan '(.)\1\1' ( PREMATCH )
abc
def
ghi
> print abcaaadefbbbghiccc | scan '(.)\1\1' ( POSTMATCH )
defbbbghiccc
ghiccc

--------------------------------------------------------------------------------
selector

パイプから入力を受け取り選択した行を出力する。

キー操作:
カーソルキー -> 移動
CTRL-D, CTRL-U -> スクロール
a -> マーク反転
ENTER -> 決定
q, CTRL-c -> キャンセル

戻り値: 入力文字列が無ければ262

-multiple スペースによる複数行選択を許す
-preserve-position カーソル位置とスクロールトップ位置を初期化しない
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> ls | selector
AUTHORS

> ls | selector -multiple
AUTHORS
CHANGELOG
main.c

--------------------------------------------------------------------------------
sort (ブロック)

ソートを行う。ブロックのコンテキストパイプには2行テキストが入っており、最初の行は左の値を次の行は右の値が入っている。
ブロックでは、左と右を比べて、その真偽値によってソートを行う。

戻り値: 入力文字列が無ければ262

-shuffle ソートの並びをランダムに行う。引数にブロックは取らない。
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "ddd eee aaa ccc bbb" | sort ( | var a b; a | -slt $b )
aaa
bbb
ccc
ddd
eee

> spit -target "ddd eee aaa ccc bbb" | sort (| var a b; a | -sgt $b )
eee
ddd
ccc
bbb
aaa

> split -target "ddd eee aaa ccc bbb" | sort -shuffle    # random sort
bbb
eee
ddd
aaa
ccc

--------------------------------------------------------------------------------
split 正規表現

パイプから得たテキストを正規表現にマッチする部分を区切りとして分解する。分解結果は複数行の文字列として出力される。
正規表現が省略されたら、"\s+"が設定される。

-target 文字列 文字列をターゲットとしてフィルターを動かす
-no-regex 正規表現じゃなくて普通の文字列としてパターンを使う
-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "aaa bbb ccc"
aaa
bbb
ccc
> print "aaa bbb ccc"  | split
aaa
bbb
ccc
> print "aaa,bbb,ccc" | split ,
aaa
bbb
ccc
> print "aaa.bbb.ccc" | split -no-regex .
aaa
bbb
ccc

--------------------------------------------------------------------------------
squeeze まとめる文字の集合

連続する文字を一つにまとめるフィルター。文字の集合の形式はtr(1)と同じです。

abc --> abc
a-c --> abc
0-3 --> 0123
^a --> a以外

引数が無い場合は全ての連続する文字を一つにまとめます。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print aaabbbcccdddeeefff | squeeze a-c | pomch
abcdddeeefff
> print aaabbbcccdddeeefff | squeeze ^a-c | pomch
aaabbbcccdef
> print あああいいいうううえええおおお | squeeze -utf8 あいうえお | pomch
あいうえお

--------------------------------------------------------------------------------
stackframe

ローカル変数の定義状況を出力する

> stackframe
ARGV: array

> def fun ( ls | var -local A B C; stackframe )
> fun
C: var
B: var
A: var
OPTIONS: hash
ARGV: array

--------------------------------------------------------------------------------
stackinfo

xyzshでメモリ管理に使われているスタックの使用状況を出力する

> stackinfo
slot size 32
pool size 128
all object number 4096

--------------------------------------------------------------------------------
strip

このフィルターはパイプのデータの前後のスペース、タブ、改行コードを取り除きます。

> print \n\naaabbbccc\n\a | strip
aaabbbccc
> print " aaa bbb ccc ddd\n\n" | strip | split
aaa
bbb
ccc
ddd

--------------------------------------------------------------------------------
sub 正規表現 (変換文字列|ブロック)

文字列を変換する。正規表現にマッチする所に変換文字列かブロックの出力が置き換えられる。
ブロックのコンテキストパイプはマッチした文字列が入っている。

変換文字列では\+英数字は特別な意味を持ち以下の文字列に置き換えられる。

グループ化された文字列 \1..\9
マッチした文字列 \&,\0
マッチ以前の文字列 \`
マッチ以後の文字列 \'
最後にマッチした文字列 \+

ブロックでは以下のグローバル変数に特定の文字列が代入されている。

グループ化された文字列 1,2,..,9
マッチした文字列 MATCH, 0
マッチ以前の文字列 PREMATCH
マッチ以後の文字列 POSTMATCH
最後にマッチした文字列 LAST_MATCH
マッチした文字列の数 MATCH_NUMBER

変換回数はグローバル変数SUB_COUNTに代入される。

-no-regex 正規表現じゃなくて普通の文字列としてパターンを使う
-ignore-case 大文字と小文字を無視する
-multi-line 複数行にまたがる、正規表現を許す。(パフォーマンスは落ちる)
-global 普通なら各行に一回のみ変換を行うが、これを付けると各行何回も変換を行う
-quiet 変換結果を出力しない。戻り値と変換結果を格納した変数のみ設定する。
-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> print abc | sub b B | pomch
aBc
> print abc | sub b ( | uc ) | pomch
aBc
> print abc | sub "a(.)c" '(\1\1)' | pomch
(bb)
> print abc | sub "a(.)c" ( var 1 1 | printf "(%s%s)" | pomch
(bb)
> print abc | sub b '(\0\0)' | pomch
a(bb)c
> print abc | sub b ( var 0 0 | printf "(%s%s)" ) | pomch
a(bb)c
> print abc | sub b '(\`\`)' | pomch
a(aa)c
> print abc | sub b ( var PREMATCH PREMATCH | printf "(%s%s)" ) | pomch
a(aa)c
> print abc | sub b "(\\\'\\\')" | pomch
a(cc)c
> print abc | sub b ( var POSTMATCH POSTMATCH | printf "(%s%s)" ) | pomch
a(cc)c
> print abcdefghij | sub '(.)c(.)' '(\+)' | pomch
a(d)efghij
> print abcdefghij | sub '(.)c(.)' ( var LAST_MATCH | printf "(%s)" ) | pomch
a(d)efghij
> print abcabcabc\n | sub -global b '' && SUB_COUNT
acacac
3
> print abc | sub "a(.)c" ( var 1 1 )
b
b
> print "a.b.c.d.e.f.g\n" | sub -no-regex -global . X
aXbXcXdXeXfXg
> print "ABCDEGHIJK\n" | sub -ignore-case c XX
ABXXDEFGHIJK
> split -target "AAA BBB CCC DDD EEE" | sub -multi-line AAA\nBBB\n XXX\n
XXX
CCC
DDD
EEE

--------------------------------------------------------------------------------
subshell (ブロック)

ブロックを実行する。コンテキストパイプにはその前のコマンドの出力結果か標準入力が入っている。
subshellというコマンド名は無くても同じ。

> subshell (print a\n; print b\n; print c\n ) | less
a
b
c
> (print a\n; print b\n; print c\n) | less
a
b
c
> print aaa\n | (| print; | print ; | print)
aaa
aaa
aaa

--------------------------------------------------------------------------------
substr (インデックス) (長さ)

このフィルターは部分文字列を取るフィルターです。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abcdefg | substr 1
bcdefg
> print abcdefg | substr 1 2
bc
> print abcdefg | substr 1 -1
bcdef
> print abcdefg | substr -1 1
g
> print abcdefg | substr -2
fg
> print abcdefg | substr -2 1
f

--------------------------------------------------------------------------------
substr_replace (置き換える文字列) (インデックス) (長さ)

このフィルターは部分文字列を置き換えるフィルターです。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abcdefg | substr_replace AAA 1 3
aAAAefg
> print abcdefg | substr_repalce AAA 1 0
aAAAbcdefg
> print abcdefg | substr_replace AAA 1 -1
aAAA
> print abcdefg | substr_replace AAA -2
abcdeAAA
> print abcdefg | substr_replace AAAr -1 0
abcdefAAAg

--------------------------------------------------------------------------------
succ

次の文字列を返すフィルター

> print abc | succ
abd
> print main001 | succ | succ
main003
> print main0.0.1 | succ | succ
main0.0.3
> print 0.9.9 | succ
1.0.0

--------------------------------------------------------------------------------
sweep オブジェクト名1 オブジェクト名2 ... オブジェクト名x

カレントオブジェクトの属性のオブジェクトを削除する。引数が無ければ、ガベージコレクションを実行する

> ls | var A B C
> sweep A
> print $A\n
run time error
xyzsh 1: [print] no such as object(A)
> sweep          # run gabage collection
47 objects deleted

--------------------------------------------------------------------------------
time ブロック

ブロックを実行して実行時間を出力する。

> time ( sleep 1 )
1 sec(0 minuts 1 sec)

> time ( sleep 3 )
3 sec(0 minuts 3 sec)

--------------------------------------------------------------------------------
times 数値 (ブロック)

ブロックを数値回実行する。

> times 3 ( print Hello World\n )
Hello World
Hello World
Hello World

--------------------------------------------------------------------------------
tr 変換する文字の集合 変換される文字の集合

文字を置き換えるフィルター。文字の集合の形式はtr(1)と同じです。

abc --> abc
a-c --> abc
0-3 --> 0123
^a --> a以外

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abc | tr ab Z | pomch
ZZc
> print abc | tr a-z A-Z | pomch
ABC
> print abc | tr a-z B-ZA | pomch
BCD
> print abcbca | tr abc YKL | pomch
YKLKLY
> print abcdef | tr a-c ^a Z | pomch
aZZdef

--------------------------------------------------------------------------------
true

戻り値、真を返す

> if(true) ( print yes\n) else ( print no\n )
yes

--------------------------------------------------------------------------------
try (ブロック1) (ブロック2)

ブロック1を実行してエラーが起こると直ちにブロック2を実行する。エラーメッセージはブロック2のコンテキストパイプで得ることができる。エラーを起こすにはraiseコマンドを使う。

> try (
    make || raise "make error"
    sudo make install || raise "sudo make install error"
) catch ( 
    | =~ "make error" && print "catch make error\n";
    | =~ "sudo make install error" && print "catch make install error\n"
)

--------------------------------------------------------------------------------
uc 

小文字を大文字に変換するフィルター。

-byte バイトコードとして処理する
-utf8 UTF8コードとして処理する
-sjis SJISコードとして処理する
-eucjp EUCJPコードとして処理する

> print abcdefg | uc
ABCDEFG

> print あいうえおabcかきくけこ | uc -utf8
あいうえおABCかきくけこ

--------------------------------------------------------------------------------
umask 数値(8進数)

umaskを実行する。

> touch aaa
> ls -al aaa
-rw-r--r--  1 ab25cq  staff  0  3 11 15:02 aaa

> umask 000
> touch bbb
> ls -al bbb
-rw-rw-rw-  1 ab25cq  staff  0  3 11 15:03 bbb

> umask 777
> touch ccc
> ls -al ccc
----------  1 ab25cq  staff  0  3 11 15:03 ccc

> umask 644
> touch ddd
> ls -al ddd
-----w--w-  1 ab25cq  staff  0  3 11 15:03 ddd

> umask 133
> touch eee
> ls -al eee
-rw-r--r--  1 ab25cq  staff  0  3 11 15:03 eee

--------------------------------------------------------------------------------
unset 環境変数名 環境変数名2, ...., 環境変数名X

引数の環境変数を削除する。

> print aaa | export AAA
> env | grep AAA
AAA=aaa
> unset AAA
> env | grep AAA
return code is 1

--------------------------------------------------------------------------------
var 変数名1 変数名2, ... , 変数名X

フィルタとして使われない場合は変数の内容を出力する。
フィルタとして使われた場合は改行コードごとにテキストを切り分け、先頭行から順に変数に代入する。

-new オブジェクトを生成してアドレスを出力する
-local 変数をローカル変数として扱う
-shift フィルタとして使われた場合、変数への代入に使ったパイプのデータの残りを出力する
-Lw 改行コードをCRLFとして処理する
-Lm 改行コードをCRとして処理する
-Lu 改行コードをLFとして処理する
-La 改行コードをBELとして処理する

> split -target "ABC DEF GHI" | var A B C
> var A
ABC
> A
ABC
> var A B C
ABC
DEF
GHI

> print ABC | var -new | ref X
> var X
ABC
> X
ABC

> split -target "ABC DEF GHI" | var -shift A
DEF
GHI
> var A
ABC

> split -La -target "ABC\nDEF GHI\nJKL MNO\nPQR" " " | var -La A B C
> var A
ABC
DEF
> var B
GHI
JKL
> var C
MNO
PQR

--------------------------------------------------------------------------------
while (ブロック1) (ブロック2)

ブロック1が真(戻り値が0)の間ブロック2を実行し続ける

> print 0 | var -local I; while(I | -lt 5) ( print $I\n; ++ I )
0
1
2
3
4
5

--------------------------------------------------------------------------------
write ファイル名

パイプのデータをファイルに書き込む。

戻り値: 入力文字列が無ければ262

-append パイプのデータをファイルに追記する。
-force 強制的に上書きする
-error エラー出力をファイルに書き込む。入力をそのまま出力する。

> touch aaa
> ls | write aaa
run time error
xyzsh 1: [write] The file exists. If you want to override, add -force option to "write" runinfo
return code is 8192
> ls | write -force aaa

> vim a.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    fprintf(stderr, "hello world\n");
    exit(0);
}

> gcc a.c
> ./a.out | write -error a
> cat a
hello world

--------------------------------------------------------------------------------
x 数値

文字列を数値倍大きくするフィルター。

戻り値: 入力文字列が無ければ262

> print abc | x 2 | pomch
abcabc

> print abc\n | x 2 
abc
abc

> split -target "abc def ghi" | each ( | chomp | x 2 | pomch )
abcabc
defdef
ghighi