POSIXsh(1)
是能够有各种文件描述符操作(相当于open(2)
,close(2)
和dup(2)
,等),以及read
-ing从STDIN单行。
因此,我给我们留下了可以替换cat(1)
为符合POSIX的shell脚本的印象,但是我还没有提出实际的实现方案。真的有可能,或者,cat(1)
缺少什么功能sh(1)
?(暂时忘记GNU扩展)
不要问我为什么要这么做。作为智力测验,也许吗?
cat
可以将任何文件复制到标准输出;该文件不必是文本文件。NUL
例如,它可能包含s,并且NUL
不能在sh
字符串中表示。因此,这绝对是其中的一个特征cat
,即使不是不可能,也将很难实现。[注1]
除此之外,尽管存在一些棘手的问题,您还应该能够将read
and包裹echo
在一个while
循环中。(例如,准确地再现不以换行符结尾的非空文件。)
但是,从技术上讲,它echo
只是一部分sh
而已cat
;就像一样cat
,它是一个可能不存在的实用程序(在非Posix系统上)。实际上,没有echo
的环境与没有的环境的可能性差不多cat
。如果您有sh
,则可以合理地期望找到标准的命令行实用程序。
兼容Posix的最低版本唯一接受的选项read
是-r
。但是,如果我们使用的bash实现read
,则即使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
read
精心设计了该调用中的完整选项集,以解决bash实现中的各种特质:
IFS=
避免从结果中删除结尾的空白字符。-n1
导致读取一个字符,直到定界符为止。直观地讲,-N1
会自然而然,因为-N1
忽略了定界符。但是,read
也会NUL
从输入中去除字符。由于$char
如果下一个字符是a NUL
,目的是要存储零个字符,我们可以通过使用-n1
并将定界符设置为来避免该问题,NUL
因为分隔符检查是在NUL
s剥离之前完成的,因此可以避免该问题。-d ''
将行定界符设置为NUL
。看上面。-r
避免\在输入流中被解释;这是该集中唯一的Posix兼容选项。毋庸置疑,以上内容仅是理论上的考虑,或者根据OP进行智力测验。在实践中,一个shell脚本应该做的不超过协调外部公用设施的工作,并符合POSIX标准的实用程序,如存在cat
,dd
,head
并tail
应足以满足任何文件复制需求。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句