Kotlinで$(ドルマーク)を出力する

Kotlinで$(ドルマーク)を出力する

Kotlinの文字列操作は便利だ。
ダブルクォーテーションの中で変数を直接展開することができる。

1
2
val amount = "100.00"
println("This ticket is $amount dollars.")

「100.00 dollars」を「$100.00」と出力したい。
そんなときは、

1
2
3
4
println("This ticket is ${'$'}$amount.")
println("This ticket is ${"$"}$amount.")
println("This ticket is ${'$' + amount}.")
println("This ticket is ${"$" + amount}.")

$を使って$を出力するようだ。
これで解決。

同じタグの記事
同じカテゴリの記事

html data-* 属性

html data-* 属性

今更だが、html5では任意のタグにdata-*属性を設定できる。
設定したdata属性は、簡単に取得することができる。

サンプルHTML

1
2
3
4
5
6
7
8
9
10
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>data attribute test</title>
  </head>
  <body>
    <span id="data1" data-my-test-data="hello world!">test data</span>
  </body>
</html>

サンプルスクリプト

data属性の値はdatasetを通じて取得することができる。

1
var myTestData = document.getElementById("data1").dataset.myTestData;

data属性の”data-“は取り除き、キャメルケースで指定すると取得できる。
しかし、この方法はChorme,Firefox,Edgeで成功したが、InternetExplorerでは、
ドキュメントモードがEdgeの場合にのみ動作した。
InternetExplorerがクライアントとして訪れるのであれば、datasetという新しい方法は用いずに、従来通りのgetAttributeを使う。

1
var myTestData = document.getElementById("data1").getAttribute("data-my-test-data");

name属性やclass属性を取得するのと同じく、ただ属性を取得しているだけなので、名称の変換などは行わずに指定する。

まとめ

data属性は便利だ。今まではキー情報などをtitle属性に設定してみたりしていたが、そうするとカーソルが当たった時など、その中身が見えてしまいデバッグはしやすいが、恥ずかしい場合もあった。
これで、いろいろ隠して設定できる。

同じタグの記事
同じカテゴリの記事

pyenvとvirtualenvでpython環境を構築

pyenvとvirtualenvでpython環境を構築

pyenvで複数のバージョンのpythonの切り替えが容易になった。
pyenvにvirtualenvプラグインをインストールすると、
pythonのバージョンごとの管理と、さらに同一バージョンでも、
pip環境を分けて管理できるようだ。
これで、依存性の切り分けが容易になる気がする。
pyenvにpyenv-virtualenvを追加する。

pyenvとvirtualenvのインストール

githubよりスクリプトをダウンロード(git clone)。

1
2
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
git clone https://github.com/pyenv/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

.bash_profileを編集

1
2
3
4
5
vim ~/.bash_profile
export PYENV_ROOT=$HOME/.pyenv
export PATH_$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

編集した.bash_profileを読み込む。

1
. ~/.bash_profile

特定のバージョンのpythonをインストール。

ソースをビルドするので、結構時間がかかる。

1
pyenv install 3.6.6

バージョン3.6.6をインストール。

新しいバージョンのpythonをインストールしたときは、下記のコマンドを実行する。

1
pyenv rehash

インストールしたpythonのテスト環境を作成する。

1
pyenv virtualenv 3.6.6 test-3.6.6

バージョン3.6.6のテスト環境 test-3.6.6 を作成。

テスト環境ディレクトリを作成し、そのディレクトリにtest-3.6.6を割り当てる。

1
2
3
mkdir ~/test-3.6.6
cd ~/test-3.6.6
pyenv local test-3.6.6

ホームディレクトリのtest-3.6.6に移動すると、
test-3.6.6のpython環境が動作する。

pythonのバージョン、インストールされているパッケージを確認する。

1
2
python -V
pip freeze

pythonのバージョンは3.6.6、pipではまだ何もインストールされていない環境が作成される。
この環境でpipインストールすると、test-3.6.6にインストールされ、
3.6.6やその他の環境へはpipインストールが影響しない。

インストールしたtest-3.6.6のアンインストール

1
pyenv uninstall test-3.6.6

テスト環境のみ削除される。3.6.6環境はそのまま残るため、
新たにtest-3.6.6を瞬時に作成される。

まとめ

モジュールの依存関係が、ある程度見えてきそうだ。

同じタグの記事
同じカテゴリの記事

javaでファイルの更新日時を変更する

javaでファイルの更新日時を変更する

日次バッチでファイルを作成している。
何の為かはわからないが、ファイルの更新日時をファイル作成日の0時0分0秒にしなくてはならない。
javaバッチなので、その流れでファイルの更新日時も変更する。

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
31
32
33
34
/**
 * javac -encoding utf-8 TestFileTime.java
 *
 * java -cp . TestFileTime2
 */

import java.util.Date;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.text.SimpleDateFormat;
import java.io.Writer;

public class TestFileTime2 {
    public static void main(String[] args) {
        SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd");
        String today = ymd.format(new Date());
        Path path = Paths.get(String.format("%s.txt", today));
        try (Writer w = Files.newBufferedWriter(path)) {
            w.write(today);
            w.write("\n");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        try {
            FileTime fileTime = FileTime.fromMillis(ymd.parse(today).getTime());
            Files.setLastModifiedTime(path, fileTime);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

まとめ

ここまで作ったものの、javaバッチはshellで起動しているので、
shellでtouchすればよかった。

1
2
3
FILENAME=`date '+%Y%m%d.txt'`
TODAY=`date '+%m%d0000'`
touch -t $TODAY $FILENAME
同じタグの記事
同じカテゴリの記事

pyenvでpython環境をインストール

pyenvでpython環境をインストール

python3.7.0がリリースされた。
Windows環境へのインストールは、公式サイトよりembeddable zipをダウンロードし、
PYTHONHOMEとPATH環境変数を設定して更新した。
環境変数で実行バージョンが簡単に切り替えられるので、便利。

macへのインストールは公式サイトよりinstallerをダウンロードし、
インストールして更新した。
インストールの前に旧バージョンの削除も忘れずに。
しかし、この作業が結構面倒。
インストラーはインストールはしてくれるが、削除は手作業でファイルを削除しなくてはならない。

macではpyenvを使ってバージョン管理することにする。

pyenvのインストール

githubよりスクリプトをダウンロード。

1
git clone https://github.com/pyenv/pyenv.git ~/.pyenv

.bash_profileを編集

1
2
3
4
vim ~/.bash_profile
export PYENV_ROOT=$HOME/.pyenv
export PATH_$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"

編集した.bash_profileを読み込む。

1
. ~/.bash_profile

特定のバージョンのpythonをインストール。

ソースをビルドするので、結構時間がかかる。

1
pyenv install 3.7.0

新しいバージョンのpythonをインストールしたときは、下記のコマンドを実行する。

1
pyenv rehash

インストールしたpythonを利用する。

1
pyenv global 3.7.0

バージョン確認

1
python --version

インストールしたpythonのアンインストール



1
pyenv uninstall 3.7.0

まとめ

次回から、最新版の取り込みが簡単になりそうだ。

同じタグの記事
同じカテゴリの記事

Kotlin1.2.50がリリースされていた

Kotlin1.2.50がリリースされていた

1.2.50になったからと言って何が新しくなったのかわからないが、
せっかくリリースされたので、今日のツールはKotlinで作る。
いつもなら、チョチョイとpython3を使うところだが。

ツールの仕様

日々の積み重ねで480万レコードになってしまったダンプファイルがある。
そのファイルはタブで区切られていて、特定のカラムの中の文字列の最大長が何文字か調べたい。

Pythonでならこう作る

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import codecs

with codecs.open('out1.txt', 'w', 'utf-8') as w1:
  with codecs.open('out2.txt', 'w', 'utf-8') as w2:
    with codecs.open('in.txt', 'r', 'utf-8') as r:
      for line in r:
        arr = line.strip().split('\t')
        if len(arr) >= 4:
          c0, c1, c2, c3 = arr[0:4]
          if len(c2) > 10:
            w1.write('{:03d}\t{}\t{}\n'.format(len(c2), c0, c2))
          if len(c3) > 10:
            w2.write('{:03d}\t{}\t{}\n'.format(len(c3), c0, c2))
        else:
          print('?[{}][{}]'.format(len(arr), line.strip()))

なかなか簡潔に書ける。
withの入れ子が深いけど、これくらいの長さなら気にしない。
適当なサーバで実行したら、480万レコードのファイルを調査するのに50秒かかった。

Kotlinで作ると

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.File

File("out1.txt").bufferedWriter().use { w1 ->
  File("out2.txt").bufferedWriter().use { w2 ->
    File("in.txt").forEachLine {
      val arr = it.split('\t')
      if (arr.size >= 4) {
        val (c0, c1, c2, c3) = it.split("\t")
        if (c2.length > 10) {
          w1.write("%03d\t%s\t%s\n".format(c2.length, c0, c2))
        }  
        if (c3.length > 10) {
          w2.write("%03d\t%s\t%s\n".format(c3.length, c0, c3))
        }  
      } else {
        println("?[%d][%s]".format(arr.size, it))
      }  
    }  
  }
}

閉じカッコの分、Kotlinの方が長くなってしまうが、pythonと同様に簡潔に書ける。
pythonのときと同じサーバで実行したら、同じ480万レコードのファイルを調査するのに3秒かかった。
Kotlin(java vm?)速い。

まとめ

最近、またpythonでツールを作ることが多くなっていたが、
Kotlinでの実装もなかなか楽しい。

処理速度がとても速い事にも驚いた。pythonに高速な印象はなかったが
ツールだったので、あまり遅さを気にしていなかった。
しかし、Kotlinがここまで速いのであれば、データ量に応じて率先してKotlinを使ってもいいのかもしれない。
.ktsであれば、コンパイルの手間もなくて意外と簡単に使うことができるので。

同じタグの記事
同じカテゴリの記事

PowerShell

PowerShell

エクスプローラーで、シフトキーを押しながら右クリックしたら
「PowerShellウィンドウをここに開く(S)」というメニューが存在したので、利用してみた。

環境変数の設定の仕方がわからない。

環境変数の設定

pythonを呼び出したかったので、PYTHONHOMEとPATHにpythonのパスを追加する。

1
2
$env:PYTHONHOME="C:\usr\python3"
$env:PATH="$env:PYTHONHOME;$env:PATH"

SETはいらないようだ。
$の後ろの区切りがあいまいなときは{}で括ってもよいようだ。

1
$env:PATH="${env:PYTHONHOME};${env:PATH}"

なかなか面白い。

環境変数の呼び出し

PATH環境変数の設定内容を確認する。

1
echo $env:PATH

プログラムの終了コードがわからない

ERRORLEVELではないらしい。

$LASTEXITCODE
で取得できる。

また、$?でTrue or Falseを受け取ることができる。

まとめ

ちなみに、シフトキーを押しながら右クリックしたとき、
Windows7では、
「コマンド ウィンドウをここで開く(W)」
だった。

マイクロソフトの方針としては、コマンドプロンプトよりPowerShellを使いなさいということなのだろうか。
あまり関係はないが、Windows10の「ここに開く」よりも、Windows7の「ここで開く」の方が日本語として正しい気がする。

PowerShellはコンソールに色がついたり、.NET Frameworkのオブジェクトを呼び出せたり、使いこなせるようになれば、いろいろラクできそうだ。

.NET Frameworkを使うような大きな作業をしなくても、タブキーによるパス補完で最後に”\”が付いてくれるだけでも、相当便利になっている。
コマンドプロンプトの頃は、タブ補完後に\をタイプしてから次の文字を入力していたのに、これからはタブ補完後、すぐに次の文字が入力できる。素晴らしい。

同じタグの記事
同じカテゴリの記事

JRubyを始める

Ruby(JRuby)を始める(始めた)

Javaのサードパーティー製APIをスクリプトから呼びたくて始めたJython。
python言語は容易に学習でき、あっさり使えるようになったが、
日本語が出現するたびに悩むことになる。
・Javaで取得した任意の文字コードの文字列を加工しようと思ったとき
・Javaで取得した任意の文字コードの文字列をcodecs.openで出力しようとしたとき
これは、Jythonでなくても、python2.7でも同様に苦労することになった。
str文字列と、unicode文字列の違いで実行時エラーになってしまう。
Jythonがpython3になってくれれば…
Jythonはメンテナンスが止まっていそうなので、他の言語に逃げることに。

Kotlinはコンパイルもできるが、スクリプトでも実行できるので、Kotlinに挑戦した。
Kotlinは優れている。いろいろなロジックを簡潔に書けるようになっている。
lambdaも便利だし、型推論も便利。SmartCastも理にかなっている。null safeなところも良い。
しかし、スクリプトとして少し使いたいだけの時は、ちょっと面倒。
Javaで作られたモジュールはreturn Mapだが、それは暗黙にMapと決まっているとき、キャストせずに使いたい。
null safeなKotlinだけど、Javaで作られたモジュールは、躊躇せずnullを返してくる。
Kotlinで完結させるなら良いかもしれないけど、やはりサードパティーのJavaAPIを使おうと思うと…

そこで、JRubyを使うことにした。
rubyの構文は独特な気がしたので、なかなか手を出せなかったが遂にこの時が来た。
perlが得意だったこともあるため、使ってみると懐かしさもあった。
学習の順番が良かったかもしれない。Kotlinでlambdaの良さを感じた後だったので、
rubyのlambdaが心地よい。

ここが良いruby

rubyを使っていて、ここが良いと思ったこと。

unless

ifを否定で使いたいとき、ifが「もし~ならば」に対して、unlessは「もし~でなければ」と使える。

1
2
3
4
5
a = 1
b = 2
unless a == b
    puts "not equal."
end

perlみたい。

文字列への変数展開

“#{var_name}”とすることで、文字列に変数を展開できる。

1
2
3
4
var_name = "test value"
puts "TEST1:[#{var_name}]"
puts "TEST2:[#{var_name.size}]"
puts "TEST3:[#{var_name.upcase}]"

Kotlinみたい(Kotlinは$だけど)。

n回繰り返しが簡単

10.timesで10回繰り返しが書ける。

1
2
3
10.times do |i|
    puts i
end

pythonも簡単だけど、rubyはもっと簡単。

1
2
for i in range(10)
    print(i)

pythonはブロックをインデントで表現できるので、結構短くコーディングできる。

メイン処理

スクリプトなので、スクリプトの先頭から処理が走ってしまうが、
直接実行したときのみ実行されるメソッドを定義する。

1
2
3
if __FILE__ == $0
    puts "Main"
end

pythonでも似たような感じ

1
2
if __name__ == '__main__':
    print("Main")

pythonはブロックの終端を書かなくて良いのが素敵。

まとめ

JRubyはなかなか心地よい。
構文はシンプルで、面倒が少ない。
do endは慣れる必要があるが、その程度だと思う。

しかし、サードパーティのJavaAPIを呼ぶこととなると、少し面倒なところもある。
APIがその先で読んでいるAPIのjarが読めないことがある。
JRubyはCLASSPATHを理解してくれて、そこからライブラリを探して勝手に動いてくるのだが、
たまに、明示的にrequire “xxxx.jar”しなてくはならない時がある。

JRubyを通じてrubyの使い方が理解できたので、それはそれで良かったのだが、
サードパーティJavaAPIを呼び出すのは、結果的にKotlin+Java8になりそう。

dll hellならぬjar hellに耐性があるのはKotlin+Java7(8以降)だと思う。

同じタグの記事
同じカテゴリの記事

perl正規表現で制御コードを除去する

perl正規表現で制御コードを除去する

RSSの収集をオリジナルのプログラムで行っている。
稀に制御コードが入っていることがあった。
制御コードが入っていると、オリジナルプログラムで利用しているXML::Simpleが異常終了してしまう。

なので、不要な制御コードを除去してからXML::Simpleを利用したい。

1
2
3
4
5
6
7
8
use LWP::Simple qw(get);
use XML::Simple;

my $url = "http://www.xxx.yyy/feed.rdf";
my $xml = get($url);
$xml =~ s/[[cntrl:]]//g;
my $xs = Xml::Simple-new;
my $obj = $xs->XMLin($xml);

これで制御コードが入ったRSSでも処理できるようになった。

同じタグの記事
同じカテゴリの記事

Kotlin再発見

Kotlin今日の発見

Kotlinは、javaの上にかぶせて動かすもの。
したがって、Kotlinの構文がよくわからない時は、
Javaの構文でほとんど書けてしまう。
しかし、それに甘んじてしまうと、せっかくのKotlinを活かしきることが出来ない。
たまには、マニュアルに戻ってKotlinを知ることにする。

文字列の比較に==が利用できる

今更知ってしまった。

1
2
3
4
5
6
val s1 = "AAA"
val s2 = "BBB"
val s3 = "AAA"
println("s1==s2 ? ${s1 == s2}")
println("s2==s3 ? ${s2 == s3}")
println("s3==s1 ? ${s3 == s1}")

注意:上記の例は、定数の比較なのでjavaでも正しく動くことがある。

Listへの要素追加は+=で行える。

もちろんjavaのように.add()でも追加できるが、やはりKotlin流に。

1
2
3
4
5
6
val l1 = mutableListOf<String>()
l1.add("Zero")
l1.add("One")
l1 += "Two"
l1 += "Three"
println("l1[$l1]")

なんか、スッキリする。

Listから値を取得するときは配列の様に括弧で取得できる。

もちろんjavaのように.get()でも取得できるが、やはりKotlin流に。

1
2
val l2 = listOf("Zero", "One", "Two")
println("l2[1]:${l2[1]} l2.get(2):${l2.get(2)}")

こっちもスッキリ。

Mapへ値を追加するとも+=で行える。

もちろんJavaのようにput()でも行えるが、Kotlin流に。

1
2
3
4
5
6
val m1 = mutableMapOf<String, String>()
m1.put("A", "あ")
m1.put("I", "い")
m1 += "U" to "う"
m1 += "E" to "え"
println("m1:$m1")

素晴らしい。

Mapから値を取得しようとして、キーが存在したらそれを取得し、存在しなかったら、新たに値を作成し、指定したキーで値を追加するgetOrPutというメソッドがある。

1
2
3
4
5
6
val m2 = mutableMapOf("A" to "あ", "U" to "う")
val a = m2.getOrPut("A", {"ああ"})
print("a:$a")
val i = m2.getOrPut("I", {"いい"})
print("i:$i")
print("m2:$m2")

これは便利。入力データの重複を加味しながら処理をすることはよくあるので、このメソッドを使えば繰り返しの処理がかなり綺麗に書ける。

Mapから値を取得しようとして、キーが存在したらそれを取得し、存在しなかったらデフォルト値を取得するgetOrElseというメソッドがある。

1
2
3
4
5
val m3 = mutableMapOf("A" to "あ", "U" to "う")
val a = m3.getOrElse("A", {"ああ"})
print("a:$a")
val i = m3.getOrElse("I", {"いい"})
print("i:$i")

これも使い道はあると思う。getOrPut()ほどの感動はないが。

文字列中に変数を展開するとき、toString()を明示的に書くことは薦められない。

1
2
3
val l4 = listOf("あ", "い", "う")
println("リスト:$l4")
println("リスト:${l4.toString()}")

どちらも同じように動いてくれるが、toString()を呼ぶ必要はない。
toString()も明示的で嫌いじゃないけど。

まとめ

やはり、たまには振り返らなくてはならない。
Kotlin素晴らしい。
でも、一通りわかった気がしてきてしまったので、
次はrubyに手を出したい。

Jythonに変わるJavaモジュールを使える言語として選択したKotlinだったが、
やはりコンパイルは面倒。コンパイル時間も微妙にかかるし。
コンパイルしてしまえば、Jythonの10倍くらい速く動く気がするけど。

ツールを作る上では、気軽にソースを変更したい。
なので、JRubyを。
JythonのPython2系の文字コード関連で悩まされたので、
JRubyにその辺の問題がないのであれば、早く使ってみたい。

同じタグの記事
同じカテゴリの記事