bash/
bash.rs

1// An example is based on README.md from https://github.com/philippkeller/rexpect
2
3#[cfg(unix)]
4use expectrl::{repl::spawn_bash, ControlCode, Regex};
5
6#[cfg(unix)]
7#[cfg(not(feature = "async"))]
8fn main() {
9    let mut p = spawn_bash().unwrap();
10
11    // case 1: execute
12    let hostname = p.execute("hostname").unwrap();
13    println!("Current hostname: {:?}", String::from_utf8_lossy(&hostname));
14
15    // case 2: wait until done, only extract a few infos
16    p.send_line("wc /etc/passwd").unwrap();
17    // `exp_regex` returns both string-before-match and match itself, discard first
18    let lines = p.expect(Regex("[0-9]+")).unwrap();
19    let words = p.expect(Regex("[0-9]+")).unwrap();
20    let bytes = p.expect(Regex("[0-9]+")).unwrap();
21    p.expect_prompt().unwrap(); // go sure `wc` is really done
22    println!(
23        "/etc/passwd has {} lines, {} words, {} chars",
24        String::from_utf8_lossy(&lines[0]),
25        String::from_utf8_lossy(&words[0]),
26        String::from_utf8_lossy(&bytes[0]),
27    );
28
29    // case 3: read while program is still executing
30    p.send_line("ping 8.8.8.8").unwrap(); // returns when it sees "bytes of data" in output
31    for _ in 0..5 {
32        // times out if one ping takes longer than 2s
33        let duration = p.expect(Regex("[0-9. ]+ ms")).unwrap();
34        println!("Roundtrip time: {}", String::from_utf8_lossy(&duration[0]));
35    }
36
37    p.send(ControlCode::EOT).unwrap();
38}
39
40#[cfg(unix)]
41#[cfg(feature = "async")]
42fn main() {
43    use futures_lite::io::AsyncBufReadExt;
44
45    futures_lite::future::block_on(async {
46        let mut p = spawn_bash().await.unwrap();
47
48        // case 1: wait until program is done
49        p.send_line("hostname").await.unwrap();
50        let mut hostname = String::new();
51        p.read_line(&mut hostname).await.unwrap();
52        p.expect_prompt().await.unwrap(); // go sure `hostname` is really done
53        println!("Current hostname: {hostname:?}"); // it prints some undetermined characters before hostname ...
54
55        // case 2: wait until done, only extract a few infos
56        p.send_line("wc /etc/passwd").await.unwrap();
57        // `exp_regex` returns both string-before-match and match itself, discard first
58        let lines = p.expect(Regex("[0-9]+")).await.unwrap();
59        let words = p.expect(Regex("[0-9]+")).await.unwrap();
60        let bytes = p.expect(Regex("[0-9]+")).await.unwrap();
61        p.expect_prompt().await.unwrap(); // go sure `wc` is really done
62        println!(
63            "/etc/passwd has {} lines, {} words, {} chars",
64            String::from_utf8_lossy(lines.get(0).unwrap()),
65            String::from_utf8_lossy(words.get(0).unwrap()),
66            String::from_utf8_lossy(bytes.get(0).unwrap()),
67        );
68
69        // case 3: read while program is still executing
70        p.send_line("ping 8.8.8.8").await.unwrap(); // returns when it sees "bytes of data" in output
71        for _ in 0..5 {
72            // times out if one ping takes longer than 2s
73            let duration = p.expect(Regex("[0-9. ]+ ms")).await.unwrap();
74            println!(
75                "Roundtrip time: {}",
76                String::from_utf8_lossy(duration.get(0).unwrap())
77            );
78        }
79
80        p.send(ControlCode::EOT).await.unwrap();
81    })
82}
83
84#[cfg(windows)]
85fn main() {
86    panic!("An example doesn't supported on windows")
87}