IFS的
通常,shell 对提供给的输入执行分词 读. 正如我们所见,这意味着由一个或多个空格分隔的多个单词成为输入行上的单独项目,并通过以下方式分配给单独的变量 读. 此行为由名为的 shell 变量配置 IFS的 (用于内部字段分隔符)。 默认值为 IFS的 包含一个空格、一个制表符和一个换行符,它们中的每一个都将相互分隔项目。
我们可以调整值 IFS的 控制输入到的字段的分离 读. 例如, / etc / passwd文件 文件包含使用冒号字符作为字段分隔符的数据行。 通过改变值 IFS的 对于单个冒号,我们可以使用 读 输入内容 / etc / passwd文件 并成功地将字段分成不同的变量。 在这里,我们有一个脚本可以做到这一点:
#!/斌/庆典
# read-ifs:从文件 FILE=/etc/passwd 中读取字段
#!/斌/庆典
# read-ifs:从文件 FILE=/etc/passwd 中读取字段
read -p "输入用户名 > " user_name file_info=$(grep "^$user_name:" $FILE) if [ -n "$file_info" ]; 然后
IFS=":" read user pw uid gid name home shell <<< "$file_info" echo "User = '$user'"
echo "UID = '$uid'"
echo "GID = '$gid'" echo "Full Name = '$name'" echo "Home Dir. = '$home'" echo "Shell = '$shell'"
其他
echo "没有这样的用户 '$user_name'" >&2 exit 1
fi
read -p "输入用户名 > " user_name file_info=$(grep "^$user_name:" $FILE) if [ -n "$file_info" ]; 然后
IFS=":" read user pw uid gid name home shell <<< "$file_info" echo "User = '$user'"
echo "UID = '$uid'"
echo "GID = '$gid'" echo "Full Name = '$name'" echo "Home Dir. = '$home'" echo "Shell = '$shell'"
其他
echo "没有这样的用户 '$user_name'" >&2 exit 1
fi
该脚本提示用户输入系统帐户的用户名,然后显示在用户记录中找到的不同字段 / etc / passwd文件 文件。 该脚本包含两个有趣的行。 第一个是:
file_info=$(grep "^$user_name:" $FILE)
这一行分配了一个结果 grep的 命令变量 文件信息. 使用的正则表达式 grep的 确保用户名只匹配一行 / etc / passwd文件 文件中。
第二个有趣的行是这个:
IFS=":" read user pw uid gid name home shell <<< "$file_info"
该行由三部分组成:一个变量赋值,一个 读 命令以变量名列表作为参数,以及一个奇怪的新重定向操作符。 我们先看看变量赋值。
Shell 允许在命令之前立即进行一个或多个变量赋值。 这些赋值改变了后面命令的环境。 分配的影响是暂时的; 仅在命令期间更改环境。 在我们的例子中,值 IFS的 更改为冒号字符。 或者,我们可以这样编码:
OLD_IFS="$IFS" IFS=":"
读取用户密码 uid gid 名称 home shell <<< "$file_info" IFS="$OLD_IFS"
我们在哪里存储值 IFS的,分配一个新值,执行 读 命令,然后恢复 IFS的 到它的原始价值。 显然,将变量赋值放在
命令是做同样事情的更简洁的方式。
这个 << 运算符表示一个 这里字符串. 一个 here 字符串就像一个 here 文档,只是更短,由单个字符串组成。 在我们的示例中,来自
/etc/passwd 文件被馈送到读取命令的标准输入。 我们可能会赢——
为什么选择这种相当倾斜的方法而不是:
echo "$file_info" | IFS=":" read user pw uid gid name home shell
嗯,是有原因的……
你无法阅读
虽然 读 命令通常从标准输入获取输入,您不能这样做:
echo "foo" | 读
我们希望这能奏效,但事实并非如此。 该命令似乎成功了,但 回复 变量将始终为空。 为什么是这样?
解释与外壳处理管道的方式有关。 在 打坏 (和其他外壳,例如 sh),管道创建 子壳. 这些是 shell 及其环境的副本,用于在管道中执行命令。 在我们上面的例子中, 读 在子shell中执行。
类 Unix 系统中的子 shell 创建环境的副本,供进程在执行时使用。 当进程完成时,环境的副本被销毁。 这意味着 子shell永远不能改变其父进程的环境. 读 分配变量,然后这些变量成为环境的一部分。 在上面的例子中, 读 将值“foo”赋给变量 回复 在它的子shell的环境中,但是当命令退出时,子shell和它的环境都被破坏了,赋值的效果就消失了。
在此处使用字符串是解决此行为的一种方法。 另一种方法在第 36 章中讨论。