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

bash:重定向文件时追加换行符,bash,file,newline,append,Bash,File,Newline,Append,以下是我如何逐行读取文件: while read ROW do ... done < file 因为管道创建了一个子shell,使我丢失了环境变量。 如果文件未以换行结束,则会出现问题:未读取最后一行。用后一种语法很容易解决这个问题,只需回显一个新行: (cat file; echo) | while read ROW do ... done 在前一种语法中,我如何做同样的事情,而不打开子shell或创建临时文件(列表非常大)#/bin/bash 读行时 ... 完成mypipe&wh

以下是我如何逐行读取文件:

while read ROW
do
...
done < file
因为管道创建了一个子shell,使我丢失了环境变量。 如果文件未以换行结束,则会出现问题:未读取最后一行。用后一种语法很容易解决这个问题,只需回显一个新行:

(cat file; echo) | while read ROW
do
...
done
在前一种语法中,我如何做同样的事情,而不打开子shell或创建临时文件(列表非常大)

#/bin/bash
读行时
...

完成<在所有壳中工作的方法如下:

#!/bin/sh

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

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-infle;echo)>mypipe&while-read-line;从以下位置执行echo“-->$line:

当IFS=read-r LINE | |[-n“${LINE}]时;执行
...

这样做确实会创建一个子shell,即使它是
cat
one而不是
while
one(因此OP可能不希望
while
位于子shell中也没问题。(另外,它需要
我会将
if
更改为
if[-n“$ROW”]|[“$willexit”=0]
这样空行仍然可以处理(还要注意变量周围的引号)。引号的好处是,添加
if
意味着“在第一个空行退出”,而不是“跳过空行”。如果要处理空行,只需去掉if(代码的第一个版本)这是否仍然会导致while循环中设置的env vars在它之后不被看到,我认为这就是OP不想要子shell的原因?@Oblomov在我发布后,我意识到我的答案没有意义,因为env vars from parent->subshell应该一直工作。我意识到他在说另一种方式。我更新了答案,使之成为w使用POSIX解决方案工作。我指定:使用“丢失环境变量”,我的意思是在循环内部所做的更改在外部不可见(例如计数器)。当然,在循环中,我仍然可以访问继承的变量。也许我没有正确模拟结果,但您使用的是哪种版本的bash?我使用的是bash4,在读取最后一行时确实有问题,有没有最后一行。bash 4.1.5。也许您应该检查换行的类型(\r\n或两者,mac linux或win风格)
#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
...
done < file
#!/bin/sh

willexit=0
while [ $willexit == 0 ] ; do
read ROW || willexit=1
if [ -n "$ROW"] ; then
  ...
fi
done < file
#!/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
while IFS= read -r LINE || [ -n "${LINE}" ]; do
   ...
done <file