POSIX-compliant .env syntax specification
August 7, 2024 ยท View on GitHub
POSIX-compliant .env syntax is subset of POSIX shell scripts
File format
The encoding is UTF-8
UTF-8 is already widespread and there is no need to support other encodings.
The newline code is LF only
POSIX shells treats CR as a character.
# when the newline code is CR LF
FOO=123
echo "${#FOO}" # => 4
The first line is a directive to distinguish between .env syntax dialects
# dotenv posix
FOO=123
Cannot contain null characters
The shell cannot handle the null (\0) character.
Environment variable name
The key must be followed by =
POSIX shell specification
Valid
FOO=
Invalid
FOO
Spaces or tabs can be inserted before the name
POSIX shell specification.
Valid
FOO=123
No spaces or tabs around =
POSIX shell specification.
Invalid
FOO =123
BAR= 123
The name must be [a-zA-Z_][a-zA-Z0-9_]*
POSIX shell specification.
Invalid
FOO.BAR.BAZ=123
1ABC=123
The name can have an export prefix
Many dotenv implementations support it.
Valid
export FOO=123
export BAR # Same as `export BAR="${BAR:-}"`
Comment
Lines beginning with # are comments
POSIX shell specification.
Valid
# comment
# comment
Comment after the value must have spaces or tabs before the #
POSIX shell specification.
Valid
FOO=123 # this is comment
BAR='123' # this is comment
BAZ="123" # this is comment
Invalid
FOO=123#this-is-not-comment
BAR='123'#this-is-not-comment
BAZ="123"#this-is-not-comment
Unquoted value
Cannot contain spaces or tabs
POSIX shell specification.
Invalid
FOO=123 456
Some symbols cannot be used
The following characters have a special meaning in shell scripts and cannot be used without quotes.
[ ] { } ( ) < > " ' ` ! $ & ~ | ; \ * ?
= (only for the first character)
In the POSIX shell specification, it can be used by escaping it with a backslash, but it is better to use quotes.
Invalid
URL=http://example.com?name1=value1&name2=value2
URL==ls
Note: In zsh, it is expanded to the path of ls.
Valid
URL1='http://example.com?name1=value1&name2=value2'
URL2=http://example.com/index.html#this-is-hash #this-is-comment
Note: # (without preceding spaces or tabs) can be used as a character.
Variable expansion is not available
The behavior is different for different shells, so it is not portable.
VAR="foo bar"
export VALUE=$VAR
echo "$VALUE"
# => dash, posh, yash: `foo`
# => bash, ksh, mksh, zsh: `foo bar`
Single-quoted value
The value cannot contain single quotes
POSIX shell specification. Use double quotes.
Invalid
VAR1='foo'bar'
VAR2='foo\'bar'
Cannot use variable expansion
POSIX shell specification.
Invalid
VAR='${FOO}' # this is just a string
Newlines can be inserted
Valid
VAR='line1
line2'
Not possible to close quotes in the middle of a line
This is possible in POSIX shell specification, but prohibited for simplicity of the specification.
Invalid
VAR='foo''bar'
Double-quoted value
Escaping is required when using " ` \ $ as a value
POSIX shell specification.
Invalid
VAR=" " ` \ $ "
Valid
VAR=" \" \` \\ \$ "
Except for the above, backslashes are not escape characters
POSIX shell specification.
VAR=" \a \r \n "
printf '%s' "$VAR" # => \a \r \n
NOTE: Do not investigate with echo. In some shells, echo may interpret escape characters.
The \ at the end of the line means line continuation
POSIX shell specification.
LONGLINE="https://github.com/ko1nksm\
/shdotenv/blob/main/README.md"
echo "$LONGLINE" # => https://github.com/ko1nksm/shdotenv/blob/main/README.md
Variable expansion is supported
POSIX shell specification.
Valid
BAR="bar"
VALUE="foo ${BAR} baz"
Braces are required for variable expansion
If there are no braces, the behavior may vary depending on the shell.
BAR="bar"
VALUE="foo $BAR[0] baz"
# => bash: foo bar[0] baz
# => zsh: foo baz
If the variable is not set, it treats as an empty string
POSIX shell specification
unset BAR
VALUE="foo ${BAR} baz"
echo "$VALUE" # => foo baz
Command substitution is not supported
It is not supported due to its complexity and the security risk of random command execution.