IFS的范围是什么?


0

我对IFS的范围感到困惑,不同的人似乎认为它是基于会话而不是在脚本中设置/更改后。

我的问题是,我有一段时间读取有可能空白的列,它抵消了我设置它们的变量。如果我从选项卡更改数据中的分隔符,并更新IFS以使用该新分隔符,我担心它可能会影响我的工作流程中的其他读取命令。

如果我这样做:

while IFS='|' read var1 var2 var3

这只会改变特定while循环的IFS值吗?

Answers:


3

这只会改变特定while循环的IFS值吗?

不,实际上它只会改变它的read部分。在while循环体内,之后,它将返回其默认值,因为它只会在read命令的上下文中设置。

您可以在某个文件上编写一个简单的循环来证明这一点,例如使用包含两列的CSV文件:

#!/bin/bash
while IFS="," read a b; do
  echo $a $b
done < "input.csv"
echo $IFS

输出的最后一行将出现空,因为默认情况下,IFS是<space><tab><newline>,因此$' \t\n'。有关详细信息,请参阅POSIX规范

如果您(意外?)将IFS设置为整个脚本的其他值,请将unset IFS其重置为默认值。

此外,如果通过“session”,您指的是单个脚本(或执行脚本的shell),一旦该脚本退出,该值将不会保存。当然,您的终端不会在多个会话中保留它。


@DanielListon在取消设置和设置为默认值之间存在语义差异,但Bash将其视为相同:“如果未设置IFS,或其值正好<space> <tab> <newline>,则为默认值,则...“和”如果IFS的值为空,则不会发生分词。“ - 请参阅man bash
slhck

谢谢你的纠正。当man页面将IFS中的“I”引用为“Internal”而不是正确的“Input”字段分隔符时,我应该发出警告。基于“默认”,我必须首先质疑shell设置IFS的要点或冗余。:(
Daniel Liston

2
while IFS='|' read var1 var2 var3

这只会改变特定while循环的IFS值吗?

不会。它只会更改特定的IFS值read一般而言,循环是从whiledone,它可以包括许多命令。

这里既不特别IFS也不read特别。拿这个通用代码:

( export a=0
printenv a
while a=1 printenv a && printenv a; printenv a; true; do
   printenv a
   break
done; printenv a )

结果是:

0
1
0
0
0
0

只有第二个printenv获得修改后的值!

笔记:

  • 我使用子shell有两个原因:
    1. 您可以在shell执行任何操作之前粘贴整个代码;
    2. 代码不会影响a当前shell中的变量。
  • 我使用过printenv a,不是echo $a因为在后一种情况下shell会在开始之前扩展$ashell本身看到的值echo(无论echo是内置shell还是单独的可执行文件)。语法variable=foo some_command几乎不会改变shell本身的变量(例外variable=foo export variable)。如果改为每printenv aecho $a我的代码,你会得到所有0-s。

-1

是的,根据您的代码块,仅为循环设置IFS值。一旦控件退出循环,IFS就会在进入循环之前获得其值。这不会影响同一shell脚本中的其他读取操作。我试过这样的事情:

echo "Changing IFS value to ','."
OLD_IFS_VALUE=$IFS
IFS='|'
CURRENT_IFS_VALUE=$IFS
echo "IFS value before entering the loop : $CURRENT_IFS_VALUE"
while IFS=',' read name age city gender
do
    echo $name $age $city $gender
done < "testdata1.csv"
echo "After loop value of IFS : $IFS"

所以我把IFS设置为'|' 在循环之前。在循环内部,我使用IFS值作为','。一旦控件退出循环,IFS值为“|”。


-1因为严格的答案是“不”。“一旦控制器退出循环,”应该是“一旦控制器通过read”。循环中有些地方IFS没有,。看我的回答。
Kamil Maciorowski
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.