« ◇mongoShellの20行制限回避(find,it,it,it...) | トップページ | ◇RUSTで標準入力からキーを読む »

◇rustで時刻処理をするcargo,crateプロジェクト

 単純コンパイル

rustで標準入力から1行ずつ読むには次の様にします。


// readStdin.rs
use std::io::{BufRead,BufReader};
fn main() {
   let _file = std::io::stdin();
   for _result in BufReader::new(_file).lines(){
      if let Ok(_line) = _result {
         let _chars: Vec = _line.chars().collect();
         for _c in _chars {
            print!("{}",_c);
            }
         println!("{}","");
         }
      }
   }

このプログラムでは読み込んだ1行の文字列を文字配列にして1文字ずつ標準出力に表示しています。

次の手続きでコンパイルできます。

rustc readStdin.rs

rustコンパイラのインストール法は以前の記事
  rustコンパイラ・メモ
を参照してください。

 プロジェクト(パッケージ)を作りコンパイルする

極めて単純なプログラムの場合rustcコンパイラのみで作成できますが、通常はクレートと呼ばれるライブラリをリンクする必要があり、その為にはcargoコマンドを用いてプロジェクトフォルダ(パッケージフォルダ)を作成し、ビルドします。

ここでは、標準入力から読み込んだテキスト中の10桁の数値をunixEpochと解釈し時刻文字列に変換するプログラムをビルドする例を載せます。

プログラムは次のものです。

#![allow(non_snake_case)]
use std::io::{BufRead,BufReader};
extern crate chrono;
use chrono::prelude::*;
fn printNumber(numbers_:&mut Vec<char>){
   if numbers_.len() > 0 {
      let _num: String = numbers_.iter().collect();
      if numbers_.len()==10 {
         let _timestamp:i64 = _num.parse::<i64>().unwrap();
         let _naive:NaiveDateTime
             = NaiveDateTime::from_timestamp(_timestamp+9*3600, 0);
         print!("{}",_naive);
         }
      else{
         print!("{}",_num);
         }
      }
   }
fn main() {
   let _file = std::io::stdin();
   for _result in BufReader::new(_file).lines(){
      let mut _numbers:Vec<char>=Vec::new();
      if let Ok(_line) = _result {
         let _chars: Vec<char> = _line.chars().collect();
         for _c in _chars {
            if _c >= '0' && _c <= '9'{
               _numbers.push(_c);
               }
            else{
               printNumber(&mut _numbers);
               print!("{}",_c);
               _numbers.clear();
               }
            }
         printNumber(&mut _numbers);
         println!("{}","");
         }
      }
   }

 プロジェクトフォルダを作る;cargo new

ここでは名前convUnixEpochでプロジェクトフォルダを作成します。なお、最終的な実行形式ファイルも同じ名前とします。

$ cargo new convUnixEpoch
     Created binary (application) `convUnixEpoch` package
$ tree convUnixEpoch
convUnixEpoch
|-- Cargo.toml
`-- src
    `-- main.rs

指定名のフォルダの下に

設定ファイル:Cargo.tom
ソースファイル:src/main.rs
が作成されます。

 Cargo.tomlの編集

chronoクレートを使用するのでCargo.tomlの[dependencies]にchronoを追加します。

[package]
name = "convUnixEpoch"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = "0.4"

0.4はおまじないです。

 main.rsを修正しコンパイル

main.rsには初期状態で次のコードが入っています。

fn main() {
    println!("Hello, world!");
}

これを実際のプログラムに置き替えます。

cargo build --releaseコマンドでコンパイルします。

$ cargo build --release
   Compiling convUnixEpoch v0.1.0 (/tmp/convUnixEpoch)
    Building [                             ] 0/1: convUnixEpoch(bin)
warning: crate `convUnixEpoch` should have a snake case name
  |
  = note: `#[warn(non_snake_case)]` on by default
  = help: convert the identifier to snake case: `conv_unix_epoch`

    Building [                             ] 0/1: convUnixEpoch(bin)
warning: 1 warning emitted

    Building [                             ] 0/1: convUnixEpoch(bin)
    Finished release [optimized] target(s) in 0.43s

targetフォルダが生成され、実行形式convUnixEpochが生成されます。
ここで生成される"convUnixEpoch"という名はCargo.tomlの"name"で指定した名です。

$ tree convUnixEpoch
convUnixEpoch
|-- Cargo.lock
|-- Cargo.toml
|-- src
|   `-- main.rs
`-- target
    |-- CACHEDIR.TAG
    `-- release
        |-- build
        |-- convUnixEpoch
        |-- convUnixEpoch.d
        |-- deps
        |   |-- convUnixEpoch-ee50e58cbc8026cb
        |   `-- convUnixEpoch-ee50e58cbc8026cb.d
        |-- examples
        `-- incremental

 実行形式をビルドしリリース

生成されたtarget/release/convUnixEpochは別途ライブラリなどを用意せずそれだけで実行できます。

ここではビルドを行い実行形式をbinフォルダに移動、不要なファイルを削除するスクリプトを示します。

#!/bin/bash
# UTF-8,LF
cargo build --release
if [ $? -ne 0 ];then
   echo "エラー発生"
   exit 1
fi
mkdir -p bin
echo convUnixEpoch を bin/ へ移動
mv target/release/convUnixEpoch bin
rm -rf target

次のフォルダ構造となります。

$ tree convUnixEpoch
convUnixEpoch
|-- A00_clear.sh
|-- A01_build.sh
|-- A05_test.sh
|-- Cargo.lock
|-- Cargo.toml
|-- bin
|   `-- convUnixEpoch
|-- reference.txt
`-- src
    `-- main.rs

単純な試験スクリプトを用意しました。予め作成しておいたreference.txtと結果を比較します、

#!/bin/bash
# A05_test.sh
# UTF-8,LF
bin/convUnixEpoch << EOF | tee kekka.txt
abcd1621491776eof1621491738xyz
16214917411621491745
1621491741#1621491745
ABC123XYZ
EOF
echo diff kekka.txt reference.txt
diff kekka.txt reference.txt
if [ $? -eq 0 ];then
   echo OK
else
   echo NG
fi

 ソースセットのダウンロード

この記事の本旨は、cargo newによりプロジェクトフォルダを生成する所からビルドすることですが、念のためconvUnixEpochの内容をzip化しました。

次のリンクでダウンロードできます。

convunixepoch.zip

内容は次のものです。

convUnixEpoch/
|-- A00_clear.sh
|-- A01_build.sh
|-- A05_test.sh
|-- Cargo.lock
|-- Cargo.toml
|-- reference.txt
`-- src
    `-- main.rs

|

« ◇mongoShellの20行制限回避(find,it,it,it...) | トップページ | ◇RUSTで標準入力からキーを読む »