2011-09-03 125 views
3

我正在做以下,基本上工作。 該腳本嘗試在文件中插入一些行以重寫它。Bash腳本通過循環輸入循環

但它是剝離所有空行和所有行填充。 主要問題是它不處理文件的最後一行。 我不知道爲什麼。

 while read line; do 
     <... process some things ...> 
     echo ${line}>> "${ACTION_PATH_IN}.work" 
    done < "${ACTION_PATH_IN}" 

可以做些什麼來解決這個問題?

回答

5
while IFS= read -r line; do 
    ## some work 
    printf '%s\n' "$line" >> output 
done < <(printf '%s\n' "$(cat input)") 
  • 空IFS告訴read不剝離的前緣和後空格。
  • read -r防止EOL中的反斜槓創建行延續。
  • 雙引號替換參數("$line")以防止shell對其值進行分詞和匹配。
  • 使用printf '%s\n'代替echo,因爲它處理值等像-e-n
  • < <(printf '%s\n' "$(cat input)")是LF的醜陋的方式終止的input內容時是可靠的。其他結構也是可能的,這取決於你的要求(如果你的整個while運行在一個子shell中,管道而不是從過程替換重定向)。
    如果您在處理之前確保它是LF終止的,那可能會更好。
+0

如果'IFS'已設置爲讀取,不需要最後'printf',因爲'read'實際上將讀取所有的行逐字(包括空格),因爲'cat'只是對文件內容沒有任何影響,但將它們複製到管道中。 –

+0

@Diego:'printf'foo \ n \ n bar'| bash -c'while IFS = read -r line;做printf「<<%s>> \ n」「$ line」; done''從不處理最終的非LF終止的「bar」行。來自流程替代的重定向中的'printf'是在那裏添加一個尾隨LF(如果原始內容沒有一個;這不是關於保留空白,而是要正確處理最後一行。 –

+0

@Diego:你是正確的,'read'將讀取最終的非LF終止行,但它也返回非零值,它退出循環(因此這樣的行絕不會被循環體處理)。 –

0

不讀取最後一行的一個可能原因是該文件沒有以換行符結束。總的來說,我希望它能夠工作,但這可能是爲什麼。

在MacOS X(10.7.1),我得到這個輸出,這是您所看到的行爲:

$ /bin/echo -n Hi 
Hi$ /bin/echo -n Hi > x 
$ while read line; do echo $line; done < x 
$ 

最明顯的解決方法是,以確保該文件以換行符結束。

0

第一件事情,用

echo "$line" >> ... 

注意引號。如果你不放它們,殼本身將會移除填充。

至於最後一行,這很奇怪。它可能與文件的最後一行是否由\n終止有關(這是一個很好的做法,幾乎所有的編輯都會爲你做這件事)。

3

最好,使用一個工具,如awk而不是shell的while循環。首先,awk是用於解析/操作文件,因此對於處理大文件,awk具有優勢。其次,你不必關心你是否有最後一個換行符(對於你的情況)。

因此您while read迴路的等效:

awk '{ 
    # process lines 
    # print line > "newfile.txt" 
}' file