什么是" IFS =!"

时间:2016-04-27 07:37:38

标签: shell unix sh

我试图了解IFS的用法,但有些东西我无法找到任何有关的信息。

我的示例代码:

#!/bin/sh
# (C) 2016 Ergin Bilgin

IFS=!
for LINE in $(last -a | sed '$ d')
do
    echo $LINE | awk '{print $1}'
done
unset IFS

我使用此代码逐行打印最后的用户。我完全理解IFS的用法,在这个例子中,当我使用默认的IFS时,它在我的循环内逐字逐句读取。当我使用IFS=!时,它会按照我的意愿逐行读取。这里的问题是我找不到任何关于那个"!"在任何地方。我不记得我从中学到了什么。当我谷歌关于实现相同类型的行为时,我看到其他值通常是字符串。

那么,"!"是什么意思?以及它如何给我我希望的结果?

由于

2 个答案:

答案 0 :(得分:2)

IFS=!仅为IFS设置一个不存在的值,以便您可以逐行迭代输入。虽然不建议在这里使用for循环,但最好在read循环中使用while来打印第一列,即用户名:

last | sed '$ d' | while read -r u _; do
   echo "$u"
done

答案 1 :(得分:1)

如您所知,如果last的输出有!,则脚本会分割该字符的输入行。

last的输出格式未标准化(例如,不在POSIX中),但您不太可能找到第一列包含任何内容但除了发起操作的名称的系统。例如,我看到了这个:

tom      pts/8        Wed Apr 27 04:25   still logged in    michener.jexium-island.net
tom      pts/0        Wed Apr 27 04:15   still logged in    michener.jexium-island.net
reboot   system boot  Wed Apr 27 04:02 - 04:35  (00:33)     3.2.0-4-amd64
tom      pts/0        Tue Apr 26 16:23 - down   (04:56)     michener.jexium-island.net

继续

reboot   system boot  Fri Apr  1 15:54 - 19:03  (03:09)     3.2.0-4-amd64
tom      pts/0        Fri Apr  1 04:34 - down   (00:54)     michener.jexium-island.net

wtmp begins Fri Apr  1 04:34:26 2016

使用Linux,以及其他计算机上的不同日期格式,来源等。

通过设置IFS=!,脚本将字段分隔符设置为{{1>}的输出中不太可能的值,因此每行都被读入{ {1}}没有拆分它。通常,线条在空格上分开。

但是,正如您所看到的,last的输出通常使用空格来分隔列,并将其输入LINE,无论如何都要用空格分割线。可以通过各种方式简化脚本,例如:

last
如果登录次数不足以超出命令行,那么

(从问题中的示例开始)就足够了。在检查awk输出的变化时,我注意到一台机器在几年内有大约9800行。 (在这种情况下,不使用for循环的其他通常动机是不可信的)。作为管道:

#!/bin/sh

for LINE in $(last -a | sed -e '$ d' -e 's/ .*//')
do    
    echo $LINE
done

我更改了sed表达式(OP可能从某些地方复制过,例如 Bash - remove the last line from a file ),因为它不起作用。

最后,使用last #!/bin/sh last -a | sed -e 's/ .*//' -e '/^$/d' | while IFS= read LINE do echo $LINE done 选项是不必要的,因为它提供的所有附加信息都将被丢弃。