IFS=',' /usr/bin/read 与 IFS=',' read

IFS=',' /usr/bin/read 与 IFS=',' read

语境

$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.$ which read
/usr/bin/read

$ which read
/usr/bin/read

有人可以解释为什么下面的示例 1 有效而示例 2 无效吗?

示例 1 - 裸读作品

这:

declare data
data="pig,cow,horse,rattlesnake,"
declare -a my_array
IFS=',' read -r -a my_array <<< "$data"
for item in "${my_array[@]}"; do echo "$item"; done

生产:

pig
cow
horse
rattlesnake

示例 2 - /usr/bin/read 失败

这不会产生输出:

declare data
data="pig,cow,horse,rattlesnake,"
declare -a my_array
IFS=',' /usr/bin/read -r -a my_array <<< "$data"
for item in "${my_array[@]}"; do echo "$item"; done

答案1

read是 shell 内置命令,即由 shell 本身而不是外部程序提供的命令。有关 shell 内置函数的更多信息,请参阅内置命令和非内置命令有什么区别?

read需要是内置函数,因为它修改 shell 的状态,特别是它设置包含输出的变量。外部命令不可能设置调用它们的 shell 的变量。也可以看看为什么 cd 不是一个程序?

有些系统还有一个外部命令,称为read, for有争议的合规原因。外部命令不能完成该命令的所有工作:它可以读取一行输入,但不能将 shell 变量设置为它读取的内容,因此外部命令只能用于丢弃一行输入,不去处理它。

which read不会告诉您内置函数存在,因为那不是它的工作。which它本身是 bash 和其他 Bourne 风格的 shell(不包括 zsh)中的外部命令,因此它只报告有关外部命令的信息。很少有充分的理由打电话which。找出命令名称代表什么的命令是type

bash-5.0$ type read
read is a shell builtin

答案2

read也是shell内置的,这个which不知道。尝试运行:

$ type read
read is a shell builtin

至于为什么/usr/bin/read不起作用,我不确定那是什么应用程序,因为我的系统上没有安装它,但很可能内置的 shell 就是您想要的应用程序。

答案3

read是影响当前环境的 shell 内置命令。 /usr/bin/read是在子 shell 中运行的外部命令,因此不能。

/usr/bin/read既然它实际上毫无用处,那么为什么我们还要拥有它呢?答案是 POSIX。它需要内置命令也作为外部命令存在!

例如,还有一个/usr/bin/cd命令。让我们逐步了解一下...它创建一个子 shell,运行脚本(基本上是builtin cd "$@")然后退出...所以它没有做任何有用的事情。

这种奇怪现象的基本原理描述如下:https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap01.html#tag_23_01_07

答案4

正如其他人提到的,“read”是内置的 shell。在我的系统上,没有 /usr/bin/read。但是,man read通知我:

NAME read - 从文件描述符中读取

概要 #include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

描述 read() 尝试从文件描述符 fd 中读取 count 个字节到从 buf 开始的缓冲区中。

所以,那种read是一个系统调用和编程工具。

然而!根本不要使用读取。您有“数据”并且需要一个数组。

IFS=',';my_array=( ${data[@]} )
for item in "${my_array[@]}"; do echo "$item"; done
pig
cow
horse
rattlesnake

相关内容