Rustをスクリプトとして実行する

rust-script(https://rust-script.org/)を使うとRustのソースコードスクリプトとして実行できます。Rust 1.54以上が必要です。

今回は公式のマニュアル(上記URL)からいくつか抜粋して説明します。

以下の説明はUNIX系OSで実行することを前提としています。

インストール

cargoをインストールしていれば、1コマンドで済みます。

$ cargo install rust-script

スクリプトを書く

cargo newでプロジェクトを作ってRustを書くときは依存クレートをCargo.tomlに記載しますが、rust-scriptの場合は//!から始まる行に記載します以下にコード例を示します。 1ファイルで完結するので気軽です。

#!/usr/bin/env rust-script
//! 2つの塩基配列をコマンドライン引数をとして受け取りローカルアラインメントするプログラム
//! 
//! ```cargo
//! [dependencies]
//! bio = "1.1.0"
//! ```
//!
//!  
use bio::alignment::pairwise::Aligner;
fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 3 {
        panic!("Please specify two arguments");
    }
    let seq1 = args[1].as_bytes();
    let seq2 = args[2].as_bytes();
    let score = |a: u8, b: u8| if a == b { 1i32 } else { -1i32 };
    let mut aligner = Aligner::new(-5, -1, &score);
    let alignment = aligner.local(seq1, seq2);
    println!("{}", alignment.pretty(seq1, seq2));
}

実行する

あとは他のスクリプト言語スクリプトと同じようにファイルに実行権限を付与するまたはrust-scriptコマンドに渡してあげれば実行できます。

コードを編集して一回目の実行はコンパイルが発生するので多少時間がかかりますが、コンパイル結果はキャッシュされるので二回目以降ははやいです。

$ chmod +x main.rs
$ ./main.rs AATGGCAGGACCA ATGGACCAGGA # rust-script main.rs でもOK
AATGGCA  GGACCA   
         ||||||   
       ATGGACCAGGA

ワンライナー

ワンライナー-eオプションで書けます。依存関係は --dep で指定します。

$ rust-script -e '2_f32.sqrt()'
1.4142135
$ rust-script --dep rand -e 'rand::random::<i32>()'
610692028

フィルター

Perlで標準入力の正規表現マッチ行だけを出力するといったことをする場合、

$ cat main.rs | perl -ne 'print if /^\/\/!/'
//! ```cargo
//! [dependencies]
//! bio = "1.1.0"
//! ```
//! 

となると思います。

これをrust-scriptでやると、--loopオプションとクロージャを用いて、

$ cat main.rs | rust-script --dep regex --loop 'let re = regex::Regex::new(r"^//! ").unwrap(); move |l| if re.is_match(l) { print!("{l}") }'
//! ```cargo
//! [dependencies]
//! bio = "1.1.0"
//! ```
//! 

となります。

Perlの方が簡潔ですが場合によってはRustの方が便利といったことがあるかもしれません。ただしTemplate機能を使えば多少は簡潔に書けるかもしれません。詳しくは公式マニュアルを参照してください。

snakemakeとの連携

rust-scriptで実行できるファイルはsnakemakeスクリプトとしても使用できます。このとき、Rustコード側ではsnakemakeインスタンスからinputoutputparams等で指定した値を参照できます。詳しくはこちら

rule all:
    input:
        "some_input.txt",
    output:
        "some_input.txt",
    params:
        "some_params",
    script:
        "rust_code_for_some_analysis.rs"