正如chepner所指出的,在外殼線讀循環只有這樣,才能知道一個給定的行是否是最後一個是嘗試讀取下一個一個。
您可以模擬用下面的代碼,它允許檢測期望的條件,同時仍然在處理線均勻地「偷看」的下一行。
該解決方案可能不適合每個人,因爲邏輯非常平庸,因此需要相當多的額外非顯而易見的代碼,並且處理速度也會變慢。
請注意,該代碼假定最後一行的尾部爲\n
(正如所有格式正確的多行文本輸入應具有的那樣)。
#!/usr/bin/env bash
eof=0 peekedChar= hadEmptyLine=0 lastLine=0
while IFS= read -r line || { eof=1; ((hadEmptyLine)); }; do
# Construct the 1-2 element array of lines to process in this iteration:
# - an empty line detected in the previous iteration by peeking, if applicable
((hadEmptyLine)) && aLines=('') || aLines=()
# - the line read in this iteration, with the peeked char. prepended
if ((eof)); then
# No further line could be read in this iteration; we're here only because
# $hadEmptyLine was set, which implies that the empty line we're processing
# is by definition the last one.
lastLine=1 hadEmptyLine=0
else
# Add the just-read line, with the peeked char. prepended.
aLines+=("${peekedChar}${line}")
# "Peek" at the next line by reading 1 character, which
# we'll have to prepend to the *next* iteration's line, if applicable.
# Being unable to read tells us that this is the last line.
IFS= read -n 1 peekedChar || lastLine=1
# If the next line happens to be empty, our "peeking" has fully consumed it,
# so we must tell the next iteration to insert processing of this empty line.
hadEmptyLine=$((! lastLine && ${#peekedChar} == 0))
fi
# Process the 1-2 lines.
ndx=0 maxNdx=$((${#aLines[@]} - 1))
for line in "${aLines[@]}"; do
if [[ -z $line ]]; then # an empty line
# Determine if this empty line is the last one overall.
thisEmptyLineIsLastLine=$((lastLine && ndx == maxNdx))
echo "empty line; last? $thisEmptyLineIsLastLine"
else
echo "nonempty line: [$line]"
fi
((++ndx))
done
done < file
判斷該行是否是最後一行的唯一方法是嘗試讀取* another *行並查看它是否成功。 – chepner
@chepner該死的,我有一種感覺,除了實現像這樣的東西之外它是不可能的:(。 – curiosityIsBliss
可能更容易使用像awk這樣的文本解析器 – 123