2016-04-27 102 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 
相關問題