问题
Context: I am trying to get the names of fonts installed on my Linux machine. The name is between two colons. When I run this script using zsh, it works. When I switch to sh it breaks. It probably deletes \n characters, because the output is all one line.
cmd="$(fc-list)"
names="$(echo $cmd | grep -oP "(?<=: ).*?(?=:)")"
echo $names
Which command causes the issues? Is it not POSIX compliant?
回答1:
Why does sh interpret these commands differently to zsh?
Because they are different shell the rules are different.
Which command causes the issues?
echo $cmd
and
echo $names
Is it not POSIX compliant?
The code, by itself, is valid POSIX code. The behavior of zsh shell that doesn't do word splitting is not compliant with POSIX.
In POSIX shell unquoted expansions undergo word splitting. Because default IFS is space tab and newline, these characters are erased when creating words from the result of expansion and passed as separate words to echo
which outputs them on one line. To disable word splitting (and filename expansion), you need to quote the expansion. Also prefer printf
to echo
.
cmd="$(fc-list)"
names="$(printf "%s\n" "$cmd" | grep -oP "(?<=: ).*?(?=:)")"
printf "%s\n" "$names"
来源:https://stackoverflow.com/questions/65155548/why-does-sh-interpret-these-commands-differently-to-zsh