Last active
December 23, 2024 19:34
-
-
Save mRB0/7ed3b977d7da1a65e4e6cfc5a7e512f4 to your computer and use it in GitHub Desktop.
zsh: Reference for word splitting behavior with variable and subshell expansion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
# -*- coding: utf-8 -*- | |
# The only differences I observed in the behavior of variable | |
# expansion were around how newlines and spaces are treated ("word | |
# splitting"). When word splitting is performed, newlines are turned | |
# into spaces, and consecutive spaces are collapsed into a single one. | |
# | |
# I never observed any issue with unicode characters, or special | |
# characters that are significant to the shell in regular syntax - | |
# these always passed through unmodified and uninterpreted. | |
# For debugging: Shows commands being invoked, with actual quoted | |
# arguments. | |
set -x | |
# Output some test data. | |
cmd() { | |
cat <<"EOF" | |
OneWord | |
Two Words | |
Many Spaces | |
Leading spaces! | |
An 'apostrophe', "quotes", $ sign, (parens), ? mark, \ backslash, \ | |
'An '\''apostrophe'\'', "quotes", $ sign, (parens), ? mark, \ backslash, now escaped for a shell \' | |
c'est français | |
🤣 | |
EOF | |
} | |
# NO SHELL BEHAVIOR: Store the output as a single scalar string. | |
# Spaces, newlines, special characters are intact. Either works. | |
content="$(cmd)" | |
content=$(cmd) | |
# NO SHELL BEHAVIOR: Echo the content exactly as it was stored, with | |
# spaces, newlines, special characters intact. Unlike bash, zsh | |
# doesn't perform word splitting on expanded variables by default, but | |
# you can change that with setopt SH_WORD_SPLIT. Either works. | |
echo "$content" | |
echo $content | |
# NO SHELL BEHAVIOR: Echo the content exactly, without storing it in | |
# a variable. | |
echo "$(cmd)" | |
# CAUSES SHELL BEHAVIOR: Perform word splitting: Newlines are treated | |
# as spaces, consecutive spaces are dropped, | |
echo $(cmd) | |
# CAUSES SHELL BEHAVIOR: ${=name} performs word splitting on $name | |
# even if it's quoted. | |
echo "${=content}" | |
# Any text surrounding ${=name} will get "glued" to the first & last | |
# words in $name after word splitting is performed, even if there are | |
# spaces in the surrounding text, but otherwise each word in $name | |
# gets passed as a separate argument. | |
# | |
# This split happens even if it looks like we're passing a single | |
# argument: | |
food='barbecue basil spam eggs' | |
print -rl -- "We have ${=food} and nothing else" | |
# Output: | |
# We have barbecue | |
# basil | |
# spam | |
# eggs and nothing else |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment