diff --git a/examples/methods.ion b/examples/methods.ion
index 8db2673362d29e4cf3778c15bca6b29f8507fb71..32292ba7f57ce47f1362bada295d871804a90097 100644
--- a/examples/methods.ion
+++ b/examples/methods.ion
@@ -5,3 +5,15 @@ echo $space_string
 echo $comma_string
 echo @split(space_string)
 echo @split(comma_string, ', ')
+
+let array = ["one two" "three four" "five six" "seven eight" "nine ten"]
+echo @len(array)
+for element in 0..@len(array)
+    echo @array[$element]
+end
+
+let string = "one 😉😉😉 two 😉😉😉 three 😉😉😉 four 😉😉😉 five"
+echo $len(string) $len_bytes(string)
+for grapheme in 0..$len(string)
+    echo $string[$grapheme]
+end
diff --git a/examples/methods.out b/examples/methods.out
index 128c4c4c7e452a974ba8a90f30593b3ebb21ed34..9c4b1eef09cc1c34c71d70c3352168f702f416e6 100644
--- a/examples/methods.out
+++ b/examples/methods.out
@@ -2,3 +2,49 @@ one two three four
 one, two, three, four
 one two three four
 one two three four
+5
+one two
+three four
+five six
+seven eight
+nine ten
+39 75
+o
+n
+e
+ 
+😉
+😉
+😉
+ 
+t
+w
+o
+ 
+😉
+😉
+😉
+ 
+t
+h
+r
+e
+e
+ 
+😉
+😉
+😉
+ 
+f
+o
+u
+r
+ 
+😉
+😉
+😉
+ 
+f
+i
+v
+e
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 087eb2251faed4ef30aef3cdcdcc838e2db1e654..b1e8215df45591490d1efc936d9b186dadca00bc 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -2,6 +2,7 @@
 macro_rules! get_expanders {
     ($vars:expr, $dir_stack:expr) => {
         ExpanderFunctions {
+            vars: $vars,
             tilde: &|tilde: &str| $vars.tilde_expansion(tilde, $dir_stack),
             array: &|array: &str, selection : Select| {
                 use std::iter::FromIterator;
diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs
index 6001d62ccda7d77e2083c2b8d83c159eaffdd5f9..2f33e745c36ee2539e95a99b46f873114392c223 100644
--- a/src/parser/shell_expand/mod.rs
+++ b/src/parser/shell_expand/mod.rs
@@ -12,11 +12,13 @@ use glob::glob;
 use self::braces::BraceToken;
 use self::ranges::parse_range;
 pub use self::words::{WordIterator, WordToken, Select, Index, Range};
+use shell::variables::Variables;
 
 use std::io::{self, Write};
 use types::*;
 
 pub struct ExpanderFunctions<'f> {
+    pub vars:     &'f Variables,
     pub tilde:    &'f Fn(&str) -> Option<String>,
     pub array:    &'f Fn(&str, Select) -> Option<Array>,
     pub variable: &'f Fn(&str, bool) -> Option<Value>,
@@ -225,6 +227,12 @@ pub fn expand_tokens<'a>(token_buffer: &[WordToken], expand_func: &'a ExpanderFu
                             "join" => if let Some(array) = (expand_func.array)(variable, Select::All) {
                                 slice_string(&mut output, &array.join(pattern), index);
                             },
+                            "len" => output.push_str(&UnicodeSegmentation::graphemes (
+                                expand_func.vars.get_var_or_empty(variable).as_str(), true
+                            ).count().to_string()),
+                            "len_bytes" => output.push_str(
+                                &expand_func.vars.get_var_or_empty(variable).len().to_string()
+                            ),
                             _ => {
                                 let stderr = io::stderr();
                                 let mut stderr = stderr.lock();
@@ -342,7 +350,14 @@ pub fn expand_tokens<'a>(token_buffer: &[WordToken], expand_func: &'a ExpanderFu
                     }
                 },
                 WordToken::ArrayMethod(ref array_method) => {
-                    return array_method.handle_as_array(expand_func);
+
+                    return if array_method.returns_array() {
+                        array_method.handle_as_array(expand_func)
+                    } else {
+                        let mut output = String::new();
+                        array_method.handle(&mut output, expand_func);
+                        Array::from_vec(vec![output])
+                    };
                 },
                 _ => ()
             }
@@ -418,6 +433,12 @@ pub fn expand_tokens<'a>(token_buffer: &[WordToken], expand_func: &'a ExpanderFu
                         "join" => if let Some(array) = (expand_func.array)(variable, Select::All) {
                             slice_string(&mut output, &array.join(pattern), index);
                         },
+                        "len" => output.push_str(&UnicodeSegmentation::graphemes (
+                            expand_func.vars.get_var_or_empty(variable).as_str(), true
+                        ).count().to_string()),
+                        "len_bytes" => output.push_str(
+                            &expand_func.vars.get_var_or_empty(variable).len().to_string()
+                        ),
                         _ => {
                             let stderr = io::stderr();
                             let mut stderr = stderr.lock();
@@ -476,6 +497,7 @@ mod test {
     macro_rules! functions {
         () => {
             ExpanderFunctions {
+                vars:     &Variables::default(),
                 tilde:    &|_| None,
                 array:    &|_, _| None,
                 variable: &|variable: &str, _| match variable {
diff --git a/src/parser/shell_expand/words.rs b/src/parser/shell_expand/words.rs
index d081d094581b826cdc8f182d9aa832e614879870..ab22f788959c1a6b7b4edc160c39480d9f26c010 100644
--- a/src/parser/shell_expand/words.rs
+++ b/src/parser/shell_expand/words.rs
@@ -179,8 +179,15 @@ pub struct ArrayMethod<'a> {
 }
 
 impl<'a> ArrayMethod<'a> {
+    pub fn returns_array(&self) -> bool {
+        self.method == "split"
+    }
     pub fn handle(&self, current: &mut String, expand_func: &ExpanderFunctions) {
         match self.method {
+            "len" => match expand_func.vars.get_array(self.variable) {
+                Some(array) => current.push_str(&array.len().to_string()),
+                None        => current.push_str("0")
+            },
             "split" => if let Some(variable) = (expand_func.variable)(self.variable, false) {
                 match (&self.pattern, self.selection) {
                     (&Pattern::StringPattern(pattern), Select::All) => current.push_str (
@@ -1025,10 +1032,12 @@ impl<'a> Iterator for WordIterator<'a> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use shell::variables::Variables;
 
     macro_rules! functions {
         () => {
             ExpanderFunctions {
+                vars:     &Variables::default(),
                 tilde:    &|_| None,
                 array:    &|_, _| None,
                 variable: &|_, _| None,