2014-12-28

Zsh: 擬似ポインタを使った関数の制作

これまでは簡単な関数しか作っていなかったので、結果を戻すには;
  1. 結果をechoで表示して終わる、
  2. 結果をグローバル変数に書き込む、
従って「 インタラクティブな処理(echo read)を必要とした時」には、 2.の方法しか使えないので、手間が掛かる。

そこで「 "From Bash to Z shell", O. Kiddle et.al., ISBN13:978-1-59059-379-9」を探ってみると、「Chapter 12, Variable Indirection, pp305..306」に「function double」の解説があったので試してみた;
#!/bin/zsh
double()
{
 #local i=${!1}  # Bash style didn’t work
 local i=${(P)1} # Zsh style works well.
 (( i=i*2 ))
 eval "$1='$i'"
}

echo ---- test of double ---------------
num=$((3))
echo "\$num=$num before call of 'double'"
echo -----------------------------------
set -x
double num
set +x
echo -----------------------------------
echo "\$num=$num after call of 'double'"
echo -----------------------------------

 その動作結果;
u1@MmM11[~/myZsh]% double
---- test of double ---------------
$num=3 before call of 'double'
-----------------------------------
+/Users/u1/myZsh/double:18> double num
+double:3> local 'i=3'
+double:4> (( i=i*2 ))
+double:5> eval 'num='\''6'\'
+(eval):1> num=6
+/Users/u1/myZsh/double:19> set +x
-----------------------------------
$num=6 after call of 'double'
-----------------------------------
u1@MmM11[~/myZsh]%


Googleで関連を調べると、少数ながら有用なサイトが見つかった;
  • Bash and Zsh pointer 
    • http://yogsototh.wordpress.com/2008/07/03/bash-or-zsh-pointer/
  •  Double and triple substitution in bash and zsh
    • http://unix.stackexchange.com/questions/68042/double-and-triple-substitution-in-bash-and-zsh
      • answered Mar 24 '13 at 3:24 by Gilles
  •  How to return a string value from a bash function 
    •  http://stackoverflow.com/questions/3236871/how-to-return-a-string-value-from-a-bash-function
      • answered Jul 14 '10 at 2:39 by bstpierre
これらの3つの記事を参考にして、私はトライ&エラーをしました。その結果、関数の動作を解釈出来たので紹介します。
#!/bin/zsh
double_2()        # General template for pointer like function.
{
 local p=$1       # Set a pointer,p as the address,num in $1; 
                       # like 「p=&num」 in C language.
 local i=${(P)p}  # Read the pointing value,*p & Set to a variable,i; 
                       # like 「i=*p」 in C language.
 #(( i=i*2 ))     # It works well. But, 
 i=$((i*2))       # I prefer the left form rather than the above form.
 eval "$p='$i'"   # Write new value,i to the pointing value *p.
                       # like 「*p=i」 in C language.
                  # '$i': single quotes are necessary
                       # for the variable including spaces.
}

echo ---- test of double_2 -------------

num=$((4))
echo "\$num=$num before call of 'double_2'"
echo -----------------------------------
set -x
double_2 num
set +x
echo -----------------------------------
echo "\$num=$num after call of 'double_2'"
echo ------------------------------------

 
 その動作結果;
u1@MmM11[~/myZsh]% double_2                             23:10:40
---- test of double_2 -------------
$num=4 before call of 'double_2'
-----------------------------------
+/Users/u1/myZsh/double_2:27> double_2 num
+double_2:2> local 'p=num'
+double_2:4> local 'i=4'
+double_2:7> i=8
+double_2:8> eval 'num='\''8'\'
+(eval):1> num=8
+/Users/u1/myZsh/double_2:28> set +x
-----------------------------------
$num=8 after call of 'double_2'
------------------------------------
u1@MmM11[~/myZsh]%                                             23:10:34

今回の環境をTerminalで確認した;

u1@MmM11[~]% zsh --version                                       11:03:16
zsh 5.0.2 (x86_64-apple-darwin13.0)
u1@MmM11[~]% sw_vers                                             11:03:20
ProductName:Mac OS X
ProductVersion:10.9.5
BuildVersion:13F34
u1@MmM11[~]%                                                     11:03:25


このページの履歴
  1. 開始 2014-12-28(日) 23:18:01 
  2. 追加 2014-12-29(月) 13:51:58 「Terminalで確認 」を直接htmlで放り込んだ。スペースの調節が難しい。

0 件のコメント:

コメントを投稿

注目の投稿

Terminalでの、なんちゃってViモドキ

近頃、ようやくKarabiner-Elementsに慣れてきたので、 Terminalで動作する「擬似Vi-Mode」を作って見たので、ご紹介します。 『概要』 「擬似Vi-Mode」の所以は、方向キー「←↓↑→」を通常の「hjkl」ではなくて「jkil」としました。これ...