gpt4 book ai didi

linux - 是否可以用 POSIX sh(1) 复制 cat(1)?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:19:44 24 4
gpt4 key购买 nike

POSIX sh(1) 能够进行各种文件描述符操作(等同于 open(2)close(2)dup(2), etc.) 以及 read-ing 来自 STDIN 的一行。

所以我的印象是我们可以用符合 POSIX 标准的 shell 脚本替换 cat(1),但我还没有想出一个实际的实现。这真的有可能吗?或者,sh(1) 可能缺少 cat(1) 的哪些功能? (暂时忘记 GNU 扩展)

不要问我为什么要这么做。作为智力测验,也许?

最佳答案

cat 可以复制任何文件到标准输出;该文件不需要是文本文件。例如,它可能包含 NUL,而 NUL 不能在 sh 字符串中表示。所以这肯定是 cat 的一个特性,即使不是不可能,也很难实现。 [注1]

除此之外,您应该能够将 readecho 包装在 while 循环中,尽管存在一些棘手的问题。 (例如,准确再现不以换行符结尾的非空文件。)

但是,从技术上讲,echocat 一样,都不是 sh 的一部分;就像 cat 一样,它是一个可能不存在的实用程序(在非 Posix 系统上)。实际上,没有 echo 的环境与没有 cat 的环境的可能性差不多;如果您有 sh,您就有合理的期望找到标准的命令行实用程序。


注意事项

  1. 最小的 Posix 兼容 read 接受的唯一选项是 -r。但是,如果我们有 read 的 bash 实现,我们可以逐个字符地复制文件,即使 NUL 字符实际上永远不会出现在 shell 变量中:

    while IFS= read -d '' -rn1 char; do
    if [ -z "$char" ]; then printf '\0'; else printf '%s' "$char"; fi
    done < "$1" > "$2"

    例子:

    $ printf 'foo\0bar\n\nbye' |
    > while IFS= read -d '' -rn1 char; do
    > if [ -z "$char" ]; then printf '\0'; else printf '%s' "$char"; fi
    > done |
    > hd
    00000000 66 6f 6f 00 62 61 72 0a 0a 62 79 65 |foo.bar..bye|
    0000000c

    该调用中要读取 的完整选项集经过精心设计,以解决 bash 实现中的各种特性:

    • IFS= 避免从结果中删除尾随空白字符。
    • -n1 导致读取一个字符,直到分隔符为止。直觉上,-N1 会更自然,因为 -N1 会忽略分隔符。但是,read 还会从输入中去除 NUL 字符。如果下一个字符是 NUL,目的是在 $char 中存储零个字符,我们可以通过使用 -n1 和将分隔符设置为 NUL,这是有效的,因为分隔符检查是在 NUL 被剥离之前完成的。
    • -d '' 将行分隔符设置为 NUL。见上文。
    • -r 避免在输入流中解释 \;这是集合中唯一与 Posix 兼容的选项。

    不用说,以上内容只是理论上的兴趣,或者作为 OP 的智力测验。实际上,shell 脚本应该只做协调外部实用程序的工作,以及存在的 Posix 兼容实用程序,例如 catddhead tail 应该足以满足任何文件复制需求。

关于linux - 是否可以用 POSIX sh(1) 复制 cat(1)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35678259/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com