我有一段时间的IFS读取循环来检查行中的不同匹配。
我检查并清空/空行如下:
while IFS= read -r line; do
[[ -z $line ]] && printf some stuff
我还想检查匹配的空/空是否也是文件的最后一行。我将在很多文件上运行这个脚本,它们都是:
- 以空行结尾
- 他们都是不同的长度所以我不能假设任何事情
- 他们有其他空行但不一定在最后(这就是为什么我必须区分) 提前谢谢。
答案 0 :(得分:0)
正如chepner所指出的,在一个shell读取循环中,知道某一行是否是 last 的唯一方法是尝试读取 next one 。
您可以模仿"偷看"在下一行使用下面的代码,它允许您在仍然统一处理线条的同时检测所需的条件 这个解决方案可能不适合所有人,因为逻辑是非常重要的,因此需要相当多的额外的,非显而易见的代码,并且处理速度也会降低。
请注意,代码假定最后一行有一个尾随\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