我试图了解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=!
时,它会按照我的意愿逐行阅读。这里的问题是我在任何地方都找不到关于那个"!"的任何信息。我不记得我从哪里学到的。当我在谷歌上搜索实现相同的行为时,我看到其他值通常是字符串。
那么,这个"!"的含义是什么,它如何给我我希望的结果?
谢谢
IFS=!
只是为IFS
设置一个不存在的值,以便您可以逐行迭代输入。话虽如此,不建议在这里使用 for 循环,最好在这样的while
循环中使用 read
来打印第一列,即用户名:
last | sed '$ d' | while read -r u _; do
echo "$u"
done
如您所知,如果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
中,无论如何都会拆分行 — 带有空格。 脚本可以通过多种方式简化,例如:
#!/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 - 从文件中删除最后一行),因为它不起作用。
最后,没有必要使用 last
的-a
选项,因为它提供的所有其他信息都将被丢弃。