如何可移植地检测 POSIX shellscript 和 POSIX 实用程序上未提供 POSIX 语言环境?

如何可移植地检测 POSIX shellscript 和 POSIX 实用程序上未提供 POSIX 语言环境?

到目前为止,我发现 Termux 是唯一没有 POSIX 语言环境的 POSIX 环境;结果是以下命令,例如:

awk 'BEGIN{for(i=1;i<256;i++)printf"%c",i;}'

并非输出每个非空字节; Termux 上的 awk 实际上是 GNU awk,它似乎取决于语言环境。然而,这个-b选择使其成功。

ShellShoccar-jpn/kotoriotoko 的问题(日语)我们正在讨论如何正确处理日语和其他 UTF-8 字符串,但此时讨论已经超出了兼容性;最新的想法没有想到如果 GAWK 可用但 POSIX 语言环境和 UTF-8 语言环境不可用怎么办。那么非 GAWK awk 又如何呢?也许awk '...' | xargs -I x printf x是最兼容的想法。

首先,如何检测 POSIX 语言环境不可用?到目前为止,我已经想到了这些(尚未测试过)(我还发现 Termux 从来不提供locale命令或 POSIX 语言环境;仅en_US.UTF-8可用):

# 1
POSIX_LOCALE_AVAILABLE=no
type locale >/dev/null 2>&1 && {
   locale -a |
   grep -qE '^(C|POSIX)$' &&
   POSIX_LOCALE_AVAILABLE=yes
}

# 2
export LC_ALL=C
POSIX_LOCALE_AVAILABLE=no
case "$LC_ALL" in ('C')
   POSIX_LOCALE_AVAILABLE=yes
;;esac

# 3
POSIX_LOCALE_AVAILABLE=no
case "$(
   LC_ALL=C awk 'BEGIN{for(i=1;i<256;i++)printf"%c",i;}' |
   od -A n -t x1 -v |
   tr ABCDEF abcdef |
   tr -Cd abcdef1234567890
)" in ("$(
   awk 'BEGIN{for(i=1;i<256;i++)printf"%02x",i;}'
)")
   POSIX_LOCALE_AVAILABLE=yes
;;esac

但它们适用于所有 POSIX 环境吗?如果没有,还有其他选择吗?

答案1

怎么样(也需要其他区域设置:在本例中为 UTF-8):

#!/bin/sh
export LC_ALL=C
# alternatively:
# a="$(printf \\343\\201\\202)" # actually あ
# case "$(mkdir "$a" && ls -dq "$a" && rmdir "$a")" in ("$a")
# end alternative
case "$(mkdir あ && ls -dq あ && rmdir あ)" in (あ)
  echo NO
;;(*'?'*)
  echo YES
;;(*)
  echo WTF
;;esac

上面的脚本输出 C 语言环境是否可用。

ls -q应将非 ASCII 字符替换为: 如果ing 实际上并未更改区域设置,则?此操作应失败。export

如果您是,上面未注释的版本可能会失败亚什用户并且LANG不是 UTF-8:请尝试评论一个(我不知道它是否有效)。

(PS。在 yash 2.51 版本上工作;. the_script_above.sh失败)

答案2

怎么样,正如 @schily 评论的那样:

if command -p getconf PATH | grep .; then
   : 'LC_ALL=C is available'
else
   : 'LC_ALL=C is not available'
fi

我尝试过 Termux 和 Arch GNU/Linux;看起来很有效。

相关内容