bash:重定向文件时附加换行符

时间:2011-01-18 17:24:35

标签: bash file newline append

以下是我逐行读取文件的方法:

while read ROW
do
...
done < file

我不使用其他语法

cat file | while read ROW
do
...
done

因为管道创建了一个子shell并使我丢失了环境变量。 如果文件没有以换行结束,则会出现问题:未读取最后一行。在后一种语法中很容易通过回显换行符来解决这个问题:

(cat file; echo) | while read ROW
do
...
done

如果不打开子shell或创建临时文件(列表非常大),我如何在前一种语法中执行相同操作?

4 个答案:

答案 0 :(得分:2)

#!/bin/bash

while read ROW
 ...
done < <(cat file ; echo)

答案 1 :(得分:2)

适用于所有shell的方法如下:

#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
...
done < file

一旦while read遇到EOF,直接read就会退出,因此不会处理最后一行。通过检查while之外的返回值,我们可以处理最后一行。在读取之后应该添加对$ ROW空虚的附加测试,因为否则最后一行以换行结束的文件将生成带空行的虚假执行,因此请将其设为

#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
if [ -n "$ROW"] ; then
  ...
fi
done < file

答案 2 :(得分:0)

POSIX的方法是通过命名管道。

#!/bin/sh

[ -p mypipe ] || mkfifo mypipe

(cat num7; echo) > mypipe & 

while read line; do 
  echo "-->$line<--"
  export CNT=$((cnt+1))
done < mypipe

rm mypipe

echo "CNT is '$cnt'"

输入

$ cat infile
1
2
3
4
5$

输出

$ (cat infile;echo) > mypipe & while read line; do echo "-->$line<--"; export CNT=$((cnt+1)); done < mypipe; echo "CNT is '$cnt'"
[1] 22260
-->1<--
-->2<--
-->3<--
-->4<--
-->5<--
CNT is '5'
[1]+  Done                    ( cat num7; echo ) > mypipe

答案 3 :(得分:0)

来自answer to a similar question

while IFS= read -r LINE || [ -n "${LINE}" ]; do
   ...
done <file

IFS=部分阻止read删除前导和尾随空格(请参阅this answer)。

如果您需要采取不同的反应,具体取决于文件是否有尾随换行符(例如,警告用户),则必须对while条件进行一些更改。