diff --git a/examples/command-substitutions.ion b/examples/command-substitutions.ion
index 20f7da67f0bc581a543d0ef80296ef6eff2a816c..866c4031b41410a262d39da9cf71a54ecda83788 100644
--- a/examples/command-substitutions.ion
+++ b/examples/command-substitutions.ion
@@ -1 +1,5 @@
 echo $(echo "one   two    three"    "four 'five' six")
+echo 0 "$(echo -e ' one  two  three ')" 1
+echo 0 "$(echo -e '  one\ntwo\nthree  ')" 1
+echo 0 $(echo -e ' one  two  three ') 1
+echo 0 $(echo -e '  one\ntwo\nthree  ') 1
diff --git a/examples/command-substitutions.out b/examples/command-substitutions.out
index 2159bdc89e9508b16606166a30b0b05452ea6c02..76ca69dd938838cc9e13bacd529d0e325ac9199a 100644
--- a/examples/command-substitutions.out
+++ b/examples/command-substitutions.out
@@ -1 +1,7 @@
-one   two    three four 'five' six
+one two three four 'five' six
+0  one  two  three  1
+0   one
+two
+three   1
+0 one two three 1
+0 one two three 1
diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs
index 4303bb34a4e4d82faeaf27224bf10e2ccd73cc57..4746b825374271103e52641bb9ca2f1afea30ff7 100644
--- a/src/builtins/mod.rs
+++ b/src/builtins/mod.rs
@@ -20,8 +20,8 @@ use self::source::source;
 use self::test::test;
 use self::variables::{alias, drop_alias, drop_array, drop_variable};
 
-use std::error::Error;
 use std::env;
+use std::error::Error;
 use std::io::{self, Write};
 use std::path::Path;
 
@@ -396,14 +396,12 @@ fn builtin_which(args: &[&str], shell: &mut Shell) -> i32 {
         println!("{}: function", command);
         SUCCESS
     } else {
-        for path in env::var("PATH").unwrap_or("/bin".to_string())
-                                    .split(sys::PATH_SEPARATOR) {
+        for path in env::var("PATH").unwrap_or("/bin".to_string()).split(sys::PATH_SEPARATOR) {
             let executable = Path::new(path).join(command);
             if executable.is_file() {
                 println!("{}", executable.display());
                 return SUCCESS;
             }
-
         }
 
         println!("{} not found", command);
diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs
index ab8892f887884e898db5d5a75011a4ee7050a43f..9ea965e0747efb51014bece74dbb52ee7f721e8b 100644
--- a/src/parser/shell_expand/mod.rs
+++ b/src/parser/shell_expand/mod.rs
@@ -10,6 +10,7 @@ use self::braces::BraceToken;
 use self::ranges::parse_range;
 pub(crate) use self::words::{Index, Range, Select, WordIterator, WordToken};
 use glob::glob;
+use std::str;
 use types::*;
 use unicode_segmentation::UnicodeSegmentation;
 
@@ -37,22 +38,28 @@ fn expand_process<E: Expander>(
     current: &mut String,
     command: &str,
     selection: Select,
-    expand_func: &E,
+    expander: &E,
+    quoted: bool,
 ) {
-    let mut tokens = Vec::new();
-    let mut contains_brace = false;
-
-    for token in WordIterator::new(command, false, expand_func) {
-        if let WordToken::Brace(_) = token {
-            contains_brace = true;
+    if let Some(output) = expander.command(command) {
+        if quoted {
+            let output: &str = if let Some(pos) = output.rfind(|x| x != '\n') {
+                &output[..pos + 1]
+            } else {
+                &output
+            };
+            slice(current, output, selection)
+        } else {
+            // TODO: Complete this so that we don't need any heap allocations.
+            //       All that we need is to shift bytes to the left when extra spaces are found.
+            //
+            // unsafe {
+            //     let bytes: &mut [u8] = output.as_bytes_mut();
+            //     bytes.iter_mut().filter(|b| **b == b'\n').for_each(|b| *b = b' ');
+            //     slice(current, str::from_utf8_unchecked(&bytes).trim(), selection)
+            // }
+            slice(current, &output.split_whitespace().collect::<Vec<&str>>().join(" "), selection)
         }
-        tokens.push(token);
-    }
-
-    let expanded = expand_tokens(&tokens, expand_func, false, contains_brace).join(" ");
-
-    if let Some(result) = expand_func.command(&expanded) {
-        slice(current, result, selection);
     }
 }
 
@@ -220,24 +227,24 @@ pub(crate) fn expand_tokens<E: Expander>(
                         Select::None => (),
                         Select::All => {
                             let mut temp = String::new();
-                            expand_process(&mut temp, command, Select::All, expand_func);
+                            expand_process(&mut temp, command, Select::All, expand_func, false);
                             let temp = temp.split_whitespace().collect::<Vec<&str>>();
                             output.push_str(&temp.join(" "));
                         }
                         Select::Index(Index::Forward(id)) => {
                             let mut temp = String::new();
-                            expand_process(&mut temp, command, Select::All, expand_func);
+                            expand_process(&mut temp, command, Select::All, expand_func, false);
                             output.push_str(temp.split_whitespace().nth(id).unwrap_or_default());
                         }
                         Select::Index(Index::Backward(id)) => {
                             let mut temp = String::new();
-                            expand_process(&mut temp, command, Select::All, expand_func);
+                            expand_process(&mut temp, command, Select::All, expand_func, false);
                             output
                                 .push_str(temp.split_whitespace().rev().nth(id).unwrap_or_default());
                         }
                         Select::Range(range) => {
                             let mut temp = String::new();
-                            expand_process(&mut temp, command, Select::All, expand_func);
+                            expand_process(&mut temp, command, Select::All, expand_func, false);
                             let len = temp.split_whitespace().count();
                             if let Some((start, length)) = range.bounds(len) {
                                 let res = temp.split_whitespace()
@@ -264,8 +271,9 @@ pub(crate) fn expand_tokens<E: Expander>(
                         reverse_quoting,
                     ),
                     WordToken::Whitespace(whitespace) => output.push_str(whitespace),
-                    WordToken::Process(command, _, ref index) => {
-                        expand_process(&mut output, command, index.clone(), expand_func);
+                    WordToken::Process(command, quoted, ref index) => {
+                        let quoted = if reverse_quoting { !quoted } else { quoted };
+                        expand_process(&mut output, command, index.clone(), expand_func, quoted);
                     }
                     WordToken::Variable(text, quoted, ref index) => {
                         let quoted = if reverse_quoting { !quoted } else { quoted };
@@ -312,11 +320,11 @@ pub(crate) fn expand_tokens<E: Expander>(
                 WordToken::ArrayProcess(command, _, ref index) => match *index {
                     Select::None => return Array::new(),
                     Select::All => {
-                        expand_process(&mut output, command, Select::All, expand_func);
+                        expand_process(&mut output, command, Select::All, expand_func, false);
                         return output.split_whitespace().map(From::from).collect::<Array>();
                     }
                     Select::Index(Index::Forward(id)) => {
-                        expand_process(&mut output, command, Select::All, expand_func);
+                        expand_process(&mut output, command, Select::All, expand_func, false);
                         return output
                             .split_whitespace()
                             .nth(id)
@@ -325,7 +333,7 @@ pub(crate) fn expand_tokens<E: Expander>(
                             .collect();
                     }
                     Select::Index(Index::Backward(id)) => {
-                        expand_process(&mut output, command, Select::All, expand_func);
+                        expand_process(&mut output, command, Select::All, expand_func, false);
                         return output
                             .split_whitespace()
                             .rev()
@@ -335,7 +343,7 @@ pub(crate) fn expand_tokens<E: Expander>(
                             .collect();
                     }
                     Select::Range(range) => {
-                        expand_process(&mut output, command, Select::All, expand_func);
+                        expand_process(&mut output, command, Select::All, expand_func, false);
                         if let Some((start, length)) =
                             range.bounds(output.split_whitespace().count())
                         {
@@ -372,23 +380,23 @@ pub(crate) fn expand_tokens<E: Expander>(
                     Select::None => (),
                     Select::All => {
                         let mut temp = String::new();
-                        expand_process(&mut temp, command, Select::All, expand_func);
+                        expand_process(&mut temp, command, Select::All, expand_func, false);
                         let temp = temp.split_whitespace().collect::<Vec<&str>>();
                         output.push_str(&temp.join(" "));
                     }
                     Select::Index(Index::Forward(id)) => {
                         let mut temp = String::new();
-                        expand_process(&mut temp, command, Select::All, expand_func);
+                        expand_process(&mut temp, command, Select::All, expand_func, false);
                         output.push_str(temp.split_whitespace().nth(id).unwrap_or_default());
                     }
                     Select::Index(Index::Backward(id)) => {
                         let mut temp = String::new();
-                        expand_process(&mut temp, command, Select::All, expand_func);
+                        expand_process(&mut temp, command, Select::All, expand_func, false);
                         output.push_str(temp.split_whitespace().rev().nth(id).unwrap_or_default());
                     }
                     Select::Range(range) => {
                         let mut temp = String::new();
-                        expand_process(&mut temp, command, Select::All, expand_func);
+                        expand_process(&mut temp, command, Select::All, expand_func, false);
                         if let Some((start, length)) = range.bounds(temp.split_whitespace().count())
                         {
                             let temp = temp.split_whitespace()
@@ -413,8 +421,9 @@ pub(crate) fn expand_tokens<E: Expander>(
                 WordToken::Whitespace(text) => {
                     output.push_str(text);
                 }
-                WordToken::Process(command, _, ref index) => {
-                    expand_process(&mut output, command, index.clone(), expand_func);
+                WordToken::Process(command, quoted, ref index) => {
+                    let quoted = if reverse_quoting { !quoted } else { quoted };
+                    expand_process(&mut output, command, index.clone(), expand_func, quoted);
                 }
                 WordToken::Variable(text, quoted, ref index) => {
                     let quoted = if reverse_quoting { !quoted } else { quoted };
diff --git a/src/shell/job.rs b/src/shell/job.rs
index 89858e9299b7007ef7ec6efd796b18041875fcef..1114933d13910b9234024bdf642b0f5d448b7fc7 100644
--- a/src/shell/job.rs
+++ b/src/shell/job.rs
@@ -321,11 +321,6 @@ impl RefinedJob {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use parser::Expander;
-
-    struct Empty;
-
-    impl Expander for Empty {}
 
     #[test]
     fn preserve_empty_arg() {
diff --git a/src/shell/mod.rs b/src/shell/mod.rs
index ee7e8e617e198d0efdfc7f43b8d1f316e9c33419..40ec69f97b5e471342cac6b5423648bd4c782ad7 100644
--- a/src/shell/mod.rs
+++ b/src/shell/mod.rs
@@ -42,6 +42,7 @@ use std::fs::File;
 use std::io::{self, Write};
 use std::ops::Deref;
 use std::process;
+use std::ptr;
 use std::sync::{Arc, Mutex};
 use std::sync::atomic::Ordering;
 use std::time::SystemTime;
@@ -89,6 +90,8 @@ pub struct Shell {
     /// Stores the patterns used to determine whether a command should be saved in the history
     /// or not
     ignore_setting: IgnoreSetting,
+    /// A pointer to itself which should only be used when performing a subshell expansion.
+    pointer: *mut Shell,
 }
 
 impl<'a> Shell {
@@ -112,6 +115,7 @@ impl<'a> Shell {
             break_flow:          false,
             foreground_signals:  Arc::new(ForegroundSignals::new()),
             ignore_setting:      IgnoreSetting::default(),
+            pointer:             ptr::null_mut(),
         }
     }
 
@@ -134,6 +138,7 @@ impl<'a> Shell {
             break_flow:          false,
             foreground_signals:  Arc::new(ForegroundSignals::new()),
             ignore_setting:      IgnoreSetting::default(),
+            pointer:             ptr::null_mut(),
         }
     }
 
@@ -207,6 +212,14 @@ impl<'a> Shell {
     /// To avoid infinite recursion when using aliases, the noalias boolean will be set the true
     /// if an alias branch was executed.
     fn run_pipeline(&mut self, pipeline: &mut Pipeline) -> Option<i32> {
+        // TODO: Find a way to only need to execute this once, without
+        // complicating our public API.
+        //
+        // Ensure that the shell pointer is set before executing.
+        // This is needed for subprocess expansions to function.
+        let pointer = self as *mut Shell;
+        self.pointer = pointer;
+
         let command_start_time = SystemTime::now();
         let builtins = self.builtins;
 
@@ -367,6 +380,56 @@ impl<'a> Expander for Shell {
             self.variables.get_var(variable).map(|x| x.ascii_replace('\n', ' ').into())
         }
     }
-    /// Expand a subshell expression
-    fn command(&self, command: &str) -> Option<Value> { self.variables.command_expansion(command) }
+    /// Uses a subshell to expand a given command.
+    fn command(&self, command: &str) -> Option<Value> {
+        use std::io::Read;
+        use std::os::unix::io::{AsRawFd, FromRawFd};
+        use std::process::exit;
+        use sys;
+
+        let (mut out_read, out_write) = match sys::pipe2(sys::O_CLOEXEC) {
+            Ok(fds) => unsafe { (File::from_raw_fd(fds.0), File::from_raw_fd(fds.1)) },
+            Err(why) => {
+                eprintln!("ion: unable to create pipe: {}", why);
+                return None;
+            }
+        };
+
+        match unsafe { sys::fork() } {
+            Ok(0) => {
+                // TODO: Figure out how to properly enable stdin in the child.
+                // Without this line, the parent will hang. Can test with:
+                //     echo $(read x)
+                sys::close_stdin();
+
+                // Redirect stdout in the child to the write end of the pipe.
+                // Also close the read end of the pipe because we don't need it.
+                let _ = sys::dup2(out_write.as_raw_fd(), sys::STDOUT_FILENO);
+                drop(out_write);
+                drop(out_read);
+
+                // Now obtain ownership of the child's shell through a mutable pointer,
+                // and then use that shell to execute the command.
+                let shell: &mut Shell = unsafe { &mut *self.pointer };
+                shell.on_command(command);
+
+                // Reap the child, enabling the parent to get EOF from the read end of the pipe.
+                exit(0);
+            }
+            Ok(_pid) => {
+                // Drop the write end of the pipe, because the parent will not use it.
+                drop(out_write);
+
+                // Read from the read end of the pipe into a String.
+                let mut output = String::new();
+                let _ = out_read.read_to_string(&mut output);
+
+                Some(output)
+            }
+            Err(why) => {
+                eprintln!("ion: fork error: {}", why);
+                None
+            }
+        }
+    }
 }
diff --git a/src/shell/variables/mod.rs b/src/shell/variables/mod.rs
index aca03d0a93f2932d59dff639b0031a440582f383..5df7d4486ceeef61c4afd843fffe3cee21c93295 100644
--- a/src/shell/variables/mod.rs
+++ b/src/shell/variables/mod.rs
@@ -8,7 +8,6 @@ use fnv::FnvHashMap;
 use liner::Context;
 use std::env;
 use std::io::{self, BufRead};
-use std::process;
 use sys::{self, getpid, is_root};
 use sys::variables as self_sys;
 use types::{
@@ -336,23 +335,6 @@ impl Variables {
         None
     }
 
-    #[allow(dead_code)]
-    pub(crate) fn command_expansion(&self, command: &str) -> Option<Value> {
-        if let Ok(exe) = env::current_exe() {
-            if let Ok(output) = process::Command::new(exe).arg("-c").arg(command).output() {
-                if let Ok(mut stdout) = String::from_utf8(output.stdout) {
-                    if stdout.ends_with('\n') {
-                        stdout.pop();
-                    }
-
-                    return Some(stdout.into());
-                }
-            }
-        }
-
-        None
-    }
-
     #[allow(dead_code)]
     pub(crate) fn is_hashmap_reference(key: &str) -> Option<(Identifier, Key)> {
         let mut key_iter = key.split('[');