2016-04-27 44 views
1

我想了解IFS的用法,但有些东西我找不到任何有关信息。“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=!时,它会按照我的意愿逐行读取。这里的问题是我找不到那个“!”在任何地方。我不记得我在哪里学到了。当我谷歌实现同样的行为,我看到其他值通常是字符串。

那么,那个“!”的含义是什么?以及它如何给我我想要的结果?

感谢

+1

您可以有可能与去年'-a取代所有代码| AWK 'NF> 8 {打印$ 1}'' – John1024

回答

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=!,脚本场分离器设置为一个值,该值是不可能last输出发生,所以每行被读入LINE而不分裂它。通常情况下,线条在空间上分开。

但是,如您所见,last的输出通常使用空格分隔列,并将其输入到awk中,该列将—与空格分开。该脚本可以以各种方式被简化,e.g,:

#!/bin/sh 

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

这是适当的(从问题的例子开始),如果登录的次数不够大到超出你的命令行。在检查last输出的变化时,我注意到一台机器从几年开始有大约9800行。 (在这种情况下,其他通常不使用for循环的动机是不合理的)。作为管:

#!/bin/sh 

last -a | sed -e 's/ .*//' -e '/^$/d' | while IFS= read LINE 
do 
    echo $LINE 
done 

我改变了SED表达(其可能OP从一些地方如Bash - remove the last line from a file复制),因为它不起作用。

最后,使用-a选项last是不必要的,因为它提供的所有附加信息都被丢弃。

+0

[为什么你不读与行 “为”(http://mywiki.wooledge.org/DontReadLinesWithFor)和[BashFAQ/001](HTTP:// mywiki .wooledge.org/BashFAQ/001) – anubhava

2

IFS=!仅仅设置IFS一个不存在的值,这样就可以通过线迭代输入线。说了这么多,不建议使用循环在这里,最好使用readwhile循环这样的打印第一列即用户名:

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