たかまるの雑記

たまに更新

ウェアラブルスピーカー

肩に乗せるスピーカーがほしいと思っているのだけれど、
いま売っているのは全部重く感じて、買ってない。

もう少し軽いのがあれば、と思っていたら
すごく軽いのが発表された。

www.itmedia.co.jp

重さは約88g!
他のは300gくらいだから、すごく軽い。
良い。

発売されたら試してみよう。
発売日は、2018年11月17日とのこと。

ソニーのConcept Nがほしかったけど、
商品化されないのかな。

シェルで関数のトレース表示(3)

トレース表示用の関数をつくることにした。

sample1.sh
#!/usr/bin/ksh

function f1
{
  echo f1
}

function f2
{
  echo f2
  f1
}
sample2.sh
. ./sample1.sh

function f3
{
  echo f3
  f2
}

f3


トレースオプションつきで実行
$ ksh -x sample2.sh
+ . ./sample1.sh
+ f3
f3
f2
f1
$

関数の中はトレースされない


修正する

  1. トレース表示用の__trace__関数をつくる
  2. スクリプトファイルから関数名をとる
  3. とってきた関数にtypeset -ftを設定する
    ※関数はfunctionで定義している前提
sample2.sh
$ 
. ./sample1.sh

function f3
{
  echo f3
  f2
}

__trace__() {
  set -
  if [ ! -z "$(echo ${1:-} | sed 's/[^x]//g')" -a -r ${2:-$0} ]
  then
    r='^ *function +'
    for f in $(awk "/$r/"'{sub(r,"");print}' r="$r" ${2:-$0}); do typeset -ft $f; done
  fi
  set -${1:-}
}

__trace__ $-

f3

HP-UXでは__trace__()内のsetは不要

トレースオプションつきで実行
$ ksh -x sample2.sh
+ . ./sample1.sh
+ __trace__ hxB
+ f3
+ echo f3
f3
+ f2
f2
f1
$

関数(f3)の中もトレースされる
HP-UXではkshではなくshでも良い


インクルードした関数のトレースも表示

f3実行の前に__trace__ $- ./sample1.shを入れると、
インクルードした関数のトレースも表示される

$ ksh -x sample2.sh
+ . ./sample1.sh
+ __trace__ hxB
+ __trace__ hxB ./sample1.sh
+ f3
+ echo f3
f3
+ f2
+ echo f2
f2
+ f1
+ echo f1
f1
$

関数(f2, f1)の中もトレースされる

-xをつけないとトレースは表示されない

$ ksh sample2.sh
f3
f2
f1
$


Ubuntoのkshだと、関数をfunctionname()で定義した場合で
トレースの表示あり/なしが違うみたい。

関数の呼び出しもとで-xをつけたとき、

  • functionで定義した関数のトレースは表示されない
  • name()で定義した関数のトレースは表示される

シェルで関数のトレース表示(2)

Ubuntoのtypeset -fx 関数名でトレース表示されない件はよくわからなかった。
set -xで関数もトレース表示されるから、
Ubuntoではset -xsh -xで実行することにしよう。

Hp-UXは関数内にset -xがないとトレース表示されないから
いままでは、読み込むファイルの先頭でvar=$-と、設定を変数に入れて
各関数でset -$varと設定していた。

これでsh -x fileと実行すると、関数内でset -xが実行されて
トレース表示される。

でも全部の関数にset -$varを入れるもの、あまりきれいじゃない気がする。

HP-UXtypeset -ftは関数ごとに設定できるから良いんだけど、
カレントの環境しか設定できないから、
sh -x fileみたいにファイルを実行した場合はトレース表示されない。

スクリプトファイルの中に全部の関数をtypeset -ftする関数をつくって
mainの処理を実行する前にその関数を呼べば良いのかもしれないけど、いまいち。

DEBUGをtrapしてもできるかもしれないけど、
トレース表示だけのための処理を書くのも、うまくない気がする。

難しい。

シェルで関数のトレースを表示する

HP-UXのsh/kshで関数の中をトレース表示するには関数の中でset -xを設定する
Ubuntubash/sh/kshでは関数の中でsetしなくても関数内がトレース表示される

HP-UXのsh/kshでは、typeset -fx 関数名で、関数ごとにトレース出力のON/OFFを設定できる(set -xは設定しない)
Ubuntubash/sh/kshでは、typeset -fx 関数名してもトレース出力は切り替わらない

マニュアルだとUbuntuもトレースのON/OFFを切り替えられそうだけど、自分の環境の問題?
こんどもう少し調べてみようかな。

Pythonで関数のグラフをかく

Pythonで2次関数のグラフをかく。

matplotlibnumpyをインストールする

pip install matplotlib
pip install numpy


コードをかく

import matplotlib.pyplot as plt
import numpy as np

# 0から3.1まで、0.1ずつのデータをつくる(等差数列)
x = np.arange(0, 3.1, 0.1)

# グラフにする数式
y = 2 * x ** 2

# グラフの大きさ  デフォルトは(8, 6)  800x600ピクセル
plt.figure(figsize=(5, 5), dpi=100)

# グラフのタイトル
plt.title(r'$y = 2x ^ 2$')

# x軸のラベル名
plt.xlabel(r'$x$')

# y軸のラベル名とラベル名の傾き
plt.ylabel(r'$y$', rotation=0)

# x軸の0~3までの間に4つ目盛りをつける
plt.xticks(np.linspace(0, 3, 4, endpoint=True))

# y軸の0~18までの間に4つ目盛りをつける
plt.yticks(np.linspace(0, 18, 19, endpoint=True))

# グラフの線の色や幅
plt.plot(x, y, color="blue", linewidth=2, linestyle="-")

# y軸の1と10に補助線を引く
plt.hlines([1, 10], min(x), max(x), linestyles="dashed")

# x軸の1と2と2.5に補助線を引く
plt.vlines([1, 2, 2.5], min(y), max(y), linestyles="dotted")

# (2, 8)に点をかく
plt.scatter(2, 8)

# (2.1, 8.1)にテキストをかく
plt.text(2.1, 8.1, 'text')

plt.show()


実行する
  • 実行するとグラフが表示される f:id:takamaruo:20181021235040p:plain


  • Save the figureのボタンをクリックすると画像を保存できる f:id:takamaruo:20181021235320p:plain

標準出力と標準エラー出力を別の変数に入れる(2)

つづき

takamaruo.hatenablog.com

プロセス置換のつかえないshで、stdoutとstderrを別々の変数に入れる方法はあるのだろうか。


サンプル コマンド
 command() {
  echo "[-- stdout1 --]"
  echo "[-- stdout2 --]"
  echo "[-- stderr1 --]" >&2
  echo "[-- stderr2 --]" >&2
  return 3
}


1. evalを使う

bashの時と同じようにevalと使う

unset out stdout stderr ret

eval "stderr=\"$({ stdout=$(command);ret=$?;echo "\""; typeset -p stdout; typeset -p ret; } 2>&1);"

echo $ret
echo -e "stdout=$stdout\nstderr=$stderr"
結果
3

stdout=[-- stdout1 --]
[-- stdout2 --]
stderr=[-- stderr1 --]
[-- stderr2 --]

stderrの代入でクォートしないとエラーになってしまうので、=の前に\"を入れた。
ただ、閉じる\"を最後の)の後ろに書くと、typeset (declare)のダブルクォーテーションが2重になってしまう。
なので、途中にechoを入れて"を出力してみた。
結果、エラーにはならないけど、stderrの最後に改行が入ってしまう。


2. 区切り文字を追加する

標準出力と標準エラー出力を同じ変数に入れる。
変数に入れるときに分けるための文字列を追加する。
そして、入れたあとにsedで別々の変数に分ける。

unset out stdout stderr

out=$({ echo "#####$(command)"; } 2>&1)

echo $?

stdout=$(echo "$out" | sed -nre '/#####/,$s/^(#####|)//p')
stderr=$(echo "$out" | sed -nre '/#####/,$!p')

echo -e "stdout=$stdout\nstderr=$stderr"
結果
0

stdout=[-- stdout1 --]
[-- stdout2 --]
stderr=[-- stderr1 --]
[-- stderr2 --]

別々の変数に入れることはできたけど、 設定する文字列も考えないといけないし、あんまりよくない気がする。

戻り値をとるときはこんな感じ。

out=$({ a=$(command);b=$?;echo "#####$a";return $b; } 2>&1)

echo $?
0


最初のevalを使う方法のダブルクォーテーションがなぞ。
これが解決できれば良いのだけれど、ぜんぜんわからない。
この件についてはkshがいいですね。

シェルでコマンドの標準出力と標準エラー出力を別の変数に入れる

コマンドの標準出力と標準エラー出力を別々の変数に格納する

サンプルのコマンド
function command {
  echo "[-- stdout --]"
  echo "[-- stderr --]" >&2
  return 3
}


1. 標準エラー出力をファイルに書く

ファイルに書いてあとから読む方法は、
わかりやすいし、コマンドの戻り値もとれる

tmpfile=$(mktemp --tmpdir=.)
stdout=$(command 2>$tmpfile)
echo $?
stderr=$(cat $tmpfile)
rm $tmpfile
echo stdout=$stdout stderr=$stderr
結果
3
stdout=[-- stdout --] stderr=[-- stderr --]

でも、ファイルをつくりたくない。


2. eval、コマンド置換、プロセス置換を使う

こんな感じにコマンド置換やプロセス置換をしてevalに渡す

stdout= stderr=

eval "$((command) 2> >(stderr=$(cat);typeset -p stderr) > >(stdout=$(cat);typeset -p stdout))"

echo $?
echo stdout=$stdout stderr=$stderr
結果
0
stdout=[-- stdout --] stderr=[-- stderr --]

evaldeclare -- stdout="xxdeclare -- stderr="xx"が実行されることで変数に設定される
typeset -p namedeclare -- name=value"を出力する

戻り値はとれない。 別の変数に設定すればとれる。

stdout= stderr=

eval "$((command) 2> >(stderr=$(cat);typeset -p stderr) > >(stdout=$(cat);typeset -p stdout);ret=$?;typeset -p ret)"

echo stdout=$stdout stderr=$stderr ret=$ret
結果
stdout=[-- stdout --] stderr=[-- stderr --] ret=3

戻り値が別の変数になってしまうのが残念。


3. kshを使う

kshだとシンプルにできる

stdout= stderr=

stderr=${ { stdout=$(command); } 2>&1; }

echo $?
echo stdout=$stdout stderr=$stderr
結果
3
stdout=[-- stdout --] stderr=[-- stderr --]

戻り値もとれるし、良い。