从该命令的 bash 手册页read
:
从标准输入或从作为 -u 选项的参数提供的文件描述符 fd 读取一行,按照上面的单词拆分中所述拆分为单词,并将第一个单词分配给名字,...
现在我尝试了以下方法:
IFS=,
echo ' a b,c d'|read -n 4 x y
echo ".$x. .$y."
我预计输出是
. a b. .c d.
因为由于更改,分词应该发生在逗号而不是空格处,但实际输出是
.a. ..
这让我很困惑。看起来.a.
分词仍然是在空格处完成的,但至少y
应该设置为b
,而不是空的。
我不禁觉得我误解了手册页中有关该read
命令的解释。
顺便说一句,我正在使用 bash 4.4.12。
答案1
它工作得很好:
$ IFS=,; echo ' a b,c d' | { read x y; declare -p x y;}
declare -- x=" a b"
declare -- y="c d"
笔记
因为它在管道中,所以该
read
语句位于子 shell 中。变量x
和 的y
范围仅限于该子 shell。在上面,我们添加了花括号,以便该declare
语句与该语句位于同一子 shell 中read
。这样,声明输出就会显示读取的 x 和 y 值。如果我们删除大括号,则该
declare
语句不再位于同一子 shell 中,并且x
和的值y
也不会保留。观察:$ x=hot; y=cold; IFS=,; echo ' a b,c d' | read -n 4 x y; declare -p x y declare -- x="hot" declare -- y="cold"
为了避免子shell限制,我们可以使用here-string:
$ IFS=,; read x y <<<' a b,c d'; declare -p x y declare -- x=" a b" declare -- y="c d"
使用here-string,语句位于主 shell 中,并且和
read
的值不会丢失。x
y
-n 4
限制read
为 4 个字符。这可能不是你想要的。观察:$ IFS=,; echo ' a b,c d' | { read -n 4 x y; declare -p x y;} declare -- x=" a b" declare -- y=""
这里,
x
占据了全部 4 个字符(空格也算作字符),没有读取任何字符y
。作为佩萨,也可以只为执行一个命令而在本地分配 shell 变量。由于对 IFS 的更改可能会在后续命令中导致不必要的副作用,因此这是一个好主意。因此:
$ IFS=, read x y <<<' a b,c d'; declare -p x y declare -- x=" a b" declare -- y="c d"
上述命令运行后,
IFS
返回到之前的值。