Rust echo implementation that supports command line options
Thanks to @Shepmaster's comment referring to one of his previous answers, I was able to make the process nicer, by using env::args as an Iterator.  

By doing so, it became much easier to switch to using a match statement, and avoids all the string concatenation I mentioned in my question.

I've also managed to add the conversion from hex and octal values to chars by making use of std::u8::from_str_radix in conjunction with std::string::String::trim_start_matches

I therefore now have the following:

// echo in rust - display a line of text
use std::env;
use std::u8;

static HELP: &amp;'static str = "\
echo the STRING(s) to standard output.\n\
-n     do not output the trailing newline\n\
-e     enable intepretation of backslash escapes\n\
-E     disable intepretation of backslash escapes (default)\n\
--help display this help and exit

If -e is in effect, the following sequence are recognized:

  \\\\    backslash
  \\a    alert (BEL)
  \\b    backspace
  \\c    produce no futher output
  \\e    escape
  \\f    form feed
  \\n    new line
  \\r    carriage return
  \\t    horizontal tab
  \\v    vertical tab
  \\0NNN byte with octal value NNN (1 to 3 digits)
  \\xHH  byte with hexadecimal value HH (1 to 2 digits)
";

fn main() {
    let mut nl: bool = true; // the "-n" flag can be used to indicate no new line
    let mut escape: bool = false; // Disable interpretation of backslashes
    let mut args_done = false; // Argument parsing done
    let mut first = true; // Correct the printing spacing

    for arg in env::args().skip(1) {
        if !args_done {
            match arg.as_ref() {
                "-n" =&gt; nl = false,
                "-e" =&gt; escape = true,
                "-E" =&gt; escape = false,
                "--help" =&gt; print!("{}", HELP),
                _ =&gt; args_done = true,
            }
        }

        if args_done {
            let mut datum: String = arg;
            if escape {
                datum = datum.replace("\\\\", "\\"); // backslash
                datum = datum.replace("\\a", ""); // alert (BEL)
                datum = datum.replace("\\b", ""); // backspace
                datum = datum.replace("\\c", ""); // produce no further output
                datum = datum.replace("\\e", ""); // escape
                datum = datum.replace("\\f", ""); // form feed
                datum = datum.replace("\\n", ""); // new line
                datum = datum.replace("\\r", ""); // carriage return
                datum = datum.replace("\\t", ""); // horizontal tab
                datum = datum.replace("\\v", ""); // vertical tab

                if datum.starts_with("\\x") &amp;&amp; 3 &lt;= datum.len() &amp;&amp; datum.len() &lt;= 4 {
                    // Hex values with at most 2 digits
                    let value = datum.trim_start_matches("\\x");
                    let chr = u8::from_str_radix(value, 16).unwrap() as char;
                    datum = chr.to_string();
                }

                if datum.starts_with("\\0") &amp;&amp; 3 &lt;= datum.len() &amp;&amp; datum.len() &lt;= 5 {
                    // Octal values with at most 3 digits
                    let value = datum.trim_start_matches("\\0");

                    let chr = u8::from_str_radix(value, 8);
                    // The maximum octal value for a byte is 377.
                    // Check that this conversion was successful.
                    if chr.is_ok() {
                        let x = chr.unwrap() as char;
                        datum = x.to_string();
                    }
                }
            }
            if first {
                print!("{}", datum);
                first = false;
            } else {
                print!(" {}", datum);
            }
        }
    }
    if nl {
        println!();
    }
}


This now adds an extra first flag for correct formatting, but it's okay for what is done here.