diff --git a/news/co.rst b/news/co.rst
new file mode 100644
index 00000000..2cf43847
--- /dev/null
+++ b/news/co.rst
@@ -0,0 +1,23 @@
+**Added:**
+
+* <news item>
+
+**Changed:**
+
+* <news item>
+
+**Deprecated:**
+
+* <news item>
+
+**Removed:**
+
+* <news item>
+
+**Fixed:**
+
+* ``xonsh.lib.subprocess.check_output()`` now properly captures output.
+
+**Security:**
+
+* <news item>
diff --git a/news/space-logical.rst b/news/space-logical.rst
new file mode 100644
index 00000000..1636a4d3
--- /dev/null
+++ b/news/space-logical.rst
@@ -0,0 +1,24 @@
+**Added:**
+
+* <news item>
+
+**Changed:**
+
+* Changed the ``ExecAlias`` to only be applied when the logical operators
+  (``and``, ``or``) are surrounded by whitespace.
+
+**Deprecated:**
+
+* <news item>
+
+**Removed:**
+
+* <news item>
+
+**Fixed:**
+
+* <news item>
+
+**Security:**
+
+* <news item>
diff --git a/xonsh/aliases.py b/xonsh/aliases.py
index 54d818f2..5577ccf7 100644
--- a/xonsh/aliases.py
+++ b/xonsh/aliases.py
@@ -44,7 +44,7 @@ import xonsh.xoreutils.which as xxw
 
 @lazyobject
 def SUB_EXEC_ALIAS_RE():
-    return re.compile(r"@\(|\$\(|!\(|\$\[|!\[|\&\&|\|\||and|or")
+    return re.compile(r"@\(|\$\(|!\(|\$\[|!\[|\&\&|\|\||\s+and\s+|\s+or\s+")
 
 
 class Aliases(cabc.MutableMapping):
diff --git a/xonsh/lib/subprocess.xsh b/xonsh/lib/subprocess.xsh
index e3a56854..0f8fa810 100644
--- a/xonsh/lib/subprocess.xsh
+++ b/xonsh/lib/subprocess.xsh
@@ -25,6 +25,10 @@ def check_call(cmd, cwd=None):
 
 def check_output(cmd, cwd=None):
     """Drop in replacement for ``subprocess.check_output`` like functionality"""
-    p = run(cmd, cwd=cwd, check=True)
-    # Note the encoding is to match the expected output of check_output
-    return p.output.encode('utf-8')
+    if cwd is None:
+        with ${...}.swap(RAISE_SUBPROC_ERROR=True):
+            output = $(@(cmd))
+    else:
+        with indir(cwd), ${...}.swap(RAISE_SUBPROC_ERROR=True):
+            output = $(@(cmd))
+    return output.encode('utf-8')

[Regression] 0.9.11: ExecAlias detected for aliases that are not code blocks
In the recently released version 0.9.11, there was a change that expanded the scope of which aliases are identified as `ExecAlias` aliases. This expanded scope has caused a change that requires me to press CTRL-C to exit some kind of hanging state after such aliases are executed.

The specific change was made in e4fada56b0e9b543ae5764b44caeff6b39635d60, with this regex change, from this:

```
@lazyobject
def SUB_EXEC_ALIAS_RE():
    return re.compile(r"@\(|\$\(|!\(|\$\[|!\[")
```
to this:
```
@lazyobject
def SUB_EXEC_ALIAS_RE():
    return re.compile(r"@\(|\$\(|!\(|\$\[|!\[|\&\&|\|\||and|or")
```

The consequence of this change is that alias commands can now be detected as `ExecAlias` commands simply because they contain the substrings `and` or `or`.  The following two aliases of mine are causing these problems:

```
aliases['gl'] = 'git log --oneline --decorate --all --graph --abbrev-commit'
aliases['gpo'] = "git push --tags origin master"
```

The word "decorate" contains **or**, and in the second example the word "origin" contains **or**.

More details are given in the _how to reproduce_ section further down.

## xonfig

```
$ xonfig
+------------------+-------------------------------------------------------+
| xonsh            | 0.9.11                                                |
| Git SHA          | dd16d59d                                              |
| Commit Date      | Aug 25 13:21:16 2019                                  |
| Python           | 3.7.4                                                 |
| PLY              | 3.11                                                  |
| have readline    | False                                                 |
| prompt toolkit   | 2.0.9                                                 |
| shell type       | prompt_toolkit2                                       |
| pygments         | 2.3.1                                                 |
| on posix         | False                                                 |
| on linux         | False                                                 |
| on darwin        | False                                                 |
| on windows       | True                                                  |
| on cygwin        | <xonsh.lazyasd.LazyBool object at 0x000002CB1A86D288> |
| on msys2         | <xonsh.lazyasd.LazyBool object at 0x000002CB1A86D5C8> |
| is superuser     | False                                                 |
| default encoding | utf-8                                                 |
| xonsh encoding   | utf-8                                                 |
| encoding errors  | surrogateescape                                       |
+------------------+-------------------------------------------------------+
```

## Expected Behavior

The alias just executes as normal.

## Current Behavior

After the alias is executed, execution hangs until CTRL-C is pressed.  This happens because `ExecAlias` is used for aliases so affected.

## Steps to Reproduce

Here are two aliases that cause the problem for me:

```
aliases['gl'] = 'git log --oneline --decorate --all --graph --abbrev-commit'
aliases['gpo'] = "git push --tags origin master"
```

Each of them **contains the substring `or`**, which leads to them being detected as `ExecAlias` aliases:

```
$ aliases['gl']
ExecAlias('git log --oneline --decorate --all --graph --abbrev-commit\n', filename='<exec-alias:gl>')
```

To reproduce the problematic behaviour:

1. Run xonsh 0.9.11 in a Windows cmd prompt
2. `cd` into a git cloned repo
3. type `$ gl` to trigger the alias.
4. The git log displays. To exit the interactive log view, press `q`
5. You should see that you do not return to the xonsh prompt.
6. Hit CTRL-C to return to the xonsh prompt.

To work around the problem, split the string when setting up the alias:

```
aliases['gl'] = 'git log --oneline --decorate --all --graph --abbrev-commit'.split()
```
This way it does not become an `ExecAlias`:

```
$ aliases['gl']
['git',
 'log',
 '--oneline',
 '--decorate',
 '--all',
 '--graph',
 '--abbrev-commit']
```

Now, if you repeat the reproducer steps given above, there will be no "hang" stage after exiting the command with `q`.
diff --git a/tests/test_integrations.py b/tests/test_integrations.py
index d9bd9023..00dc338e 100644
--- a/tests/test_integrations.py
+++ b/tests/test_integrations.py
@@ -347,6 +347,22 @@ del _f
         "",
         0,
     ),
+    #
+    # test single check_output
+    #
+    (
+        """
+def _echo(args):
+    print(' '.join(args))
+aliases['echo'] = _echo
+
+from xonsh.lib.subprocess import check_output
+
+print(check_output(["echo", "hello"]).decode("utf8"))
+""",
+        "hello\n\n",
+        0,
+    ),
 ]
 
 

pip install -e .[dev]
parse_log_pytest
requirements.txt
3.7
requirements/tests.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
black==23.3.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
cfgv==3.3.1
charset-normalizer==3.4.1
click==8.1.8
codecov==2.1.13
coverage==7.2.7
distlib==0.3.9
exceptiongroup==1.2.2
filelock==3.12.2
flake8==5.0.4
identify==2.5.24
idna==3.10
importlib-metadata==4.2.0
iniconfig==2.0.0
mccabe==0.7.0
mypy-extensions==1.0.0
nodeenv==1.9.1
packaging==24.0
pathspec==0.11.2
platformdirs==2.6.2
pluggy==1.2.0
pre-commit==2.21.0
prompt_toolkit==3.0.48
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
Pygments==2.17.2
pytest==7.4.4
pytest-cov==4.1.0
pytest-flake8==1.1.3
pytest-timeout==2.3.1
PyYAML==6.0.1
requests==2.31.0
tomli==2.0.1
typed-ast==1.5.5
typing_extensions==4.7.1
urllib3==2.0.7
virtualenv==20.16.2
wcwidth==0.2.13
-e git+https://github.com/xonsh/xonsh.git@a280154b7b0eb14a9a790a9eedd971ae44daa3d1#egg=xonsh
zipp==3.15.0

name: xonsh
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - black==23.3.0
      - cfgv==3.3.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - codecov==2.1.13
      - coverage==7.2.7
      - distlib==0.3.9
      - exceptiongroup==1.2.2
      - filelock==3.12.2
      - flake8==5.0.4
      - identify==2.5.24
      - idna==3.10
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - mccabe==0.7.0
      - mypy-extensions==1.0.0
      - nodeenv==1.9.1
      - packaging==24.0
      - pathspec==0.11.2
      - platformdirs==2.6.2
      - pluggy==1.2.0
      - pre-commit==2.21.0
      - prompt-toolkit==3.0.48
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-flake8==1.1.3
      - pytest-timeout==2.3.1
      - pyyaml==6.0.1
      - requests==2.31.0
      - tomli==2.0.1
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - virtualenv==20.16.2
      - wcwidth==0.2.13
      - zipp==3.15.0
prefix: /opt/conda/envs/xonsh

tests/test_integrations.py::test_script[case16]
tests/test_integrations.py::test_printfile tests/test_integrations.py::test_printname tests/test_integrations.py::test_sourcefile
tests/test_integrations.py::test_script[case0] tests/test_integrations.py::test_script[case1] tests/test_integrations.py::test_script[case2] tests/test_integrations.py::test_script[case3] tests/test_integrations.py::test_script[case4] tests/test_integrations.py::test_script[case5] tests/test_integrations.py::test_script[case6] tests/test_integrations.py::test_script[case7] tests/test_integrations.py::test_script[case8] tests/test_integrations.py::test_script[case9] tests/test_integrations.py::test_script[case10] tests/test_integrations.py::test_script[case11] tests/test_integrations.py::test_script[case12] tests/test_integrations.py::test_script[case13] tests/test_integrations.py::test_script[case14] tests/test_integrations.py::test_script[case15] tests/test_integrations.py::test_script_stderr[case0] tests/test_integrations.py::test_single_command_no_windows[pwd-None-<lambda>] tests/test_integrations.py::test_single_command_no_windows[echo tests/test_integrations.py::test_single_command_no_windows[ls tests/test_integrations.py::test_eof_syntax_error tests/test_integrations.py::test_open_quote_syntax_error tests/test_integrations.py::test_subshells[\nwith tests/test_integrations.py::test_redirect_out_to_file[pwd-<lambda>]
xonsh/aliases.py news/space-logical.rst news/co.rst xonsh/lib/subprocess.xsh
xonsh/aliases.py news/space-logical.rst news/co.rst xonsh/lib/subprocess.xsh