首页 > 解决方案 > 为什么 sh 对这些命令的解释与 zsh 不同?

问题描述

上下文:我正在尝试获取安装在我的 Linux 机器上的字体名称。名称在两个冒号之间。当我使用 zsh 运行此脚本时,它可以工作。当我切换到 sh 时,它会中断。它可能会删除 \n 字符,因为输出都是一行。

cmd="$(fc-list)"
names="$(echo $cmd | grep -oP "(?<=: ).*?(?=:)")"
echo $names

哪个命令导致问题?它不符合 POSIX 标准吗?

标签: shellshposixzsh

解决方案


为什么 sh 对这些命令的解释与 zsh 不同?

因为它们是不同的shell,所以规则是不同的。

哪个命令导致问题?

echo $cmd

echo $names

它不符合 POSIX 标准吗?

该代码本身就是有效的 POSIX 代码。不进行分词的 zsh shell 的行为不符合 POSIX。

在 POSIX shell 中,不带引号的扩展会进行分词。因为默认的 IFS 是空格制表符和换行符,所以这些字符在从扩展结果创建单词时会被删除,并作为单独的单词传递echo,然后在一行上输出它们。要禁用分词(和文件名扩展),您需要引用扩展。也比较喜欢printfecho

cmd="$(fc-list)"
names="$(printf "%s\n" "$cmd" | grep -oP "(?<=: ).*?(?=:)")" 
printf "%s\n" "$names"

推荐阅读