如何在bash中确保一致的换行处理

时间:2013-03-21 18:06:36

标签: bash

我有一个简单的脚本,使用curl获取一些纯文本文件,将其分配给变量;稍后它会回复它并为某些行打开它,将它们放入临时文件中(我实际上想把它们放在一个数组中);然后通过他们迭代并做一些事情。 我在Mac OS X上的一台机器上运行它,它主要工作。 但是,随机发生以下任何一种情况:

  • 卷曲输出被视为一行,因此在echo / grep阶段,该东西会中断;
  • 整个tmp文件在做echo时被视为单行,并且在它上面循环(我似乎已经使用“read line”缓解了这个),所以它再次中断。

有没有什么方法可以确保一致地处理换行符?我甚至不关心如何,只要它总是一样的,如果需要,我也可以从单线卷曲输出中获得结果。

更新:来自不同的地方。登录到机器,做了一些东西,注意到脚本不起作用。跑一些命令(结果,删节,下面)测试,注销,重新登录,行为改变(回到预期的一个)。请注意for循环输出之间的区别...对于我的curl输出也是如此,其中完全相同的命令(对于所有我知道)完全相同的env以不同的方式处理换行符。 我想要做的是在每个脚本的开头运行一些命令,使其100%确定行为永远不会改变。

[root@ip-xxx-xxx-xxx-xxx ~]# cat example.txt 
ip-xxx-xxx-xxx-xxx.ec2.internal
ip-xxx-xxx-xxx-xxx.ec2.internal
[root@ip-xxx-xxx-xxx-xxx ~]# for f in `cat example.txt`; do echo "line $f"; done
line ip-xxx-xxx-xxx-xxx.ec2.internal
ip-xxx-xxx-xxx-xxx.ec2.internal
[root@ip-xxx-xxx-xxx-xxx ~]# while read f; do echo "line $f"; done < "example.txt"
line ip-xxx-xxx-xxx-xxx.ec2.internal
line ip-xxx-xxx-xxx-xxx.ec2.internal
[root@ip-xxx-xxx-xxx-xxx ~]# logout
Connection to ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com closed.
reznor-mbp:trunk2 sergey$ ssh -i ... "root@..."
Last login: ...
[root@ip-xxx-xxx-xxx-xxx ~]# for f in `cat example.txt`; do echo "line $f"; done
line ip-xxx-xxx-xxx-xxx.ec2.internal
line ip-xxx-xxx-xxx-xxx.ec2.internal

3 个答案:

答案 0 :(得分:4)

第一:不要用for读取行;用while read循环读取它们:

while read -r; do
  echo "line $REPLY"
done <example.txt

for f in $(cat example.txt)的问题是cat操作的输出在进入循环之前经过字符串拆分和glob扩展,使得行为依赖于许多变量(IFS的内容shell设置,当前目录中的文件[如果存在可能的全局扩展名称],影响如何解释globs的各种shell选项等)。 while read方法将保持一致。

第二 - 总是引用扩展出于同样的原因:"$line"避免字符串拆分和全局扩展(再次,使上述设置和变量没有实际意义),而裸$line则会发生这种情况。 / p>

最后,上面的示例使用默认的REPLY变量,因为shell在这些条件下不会修剪空白字符(即$IFS中找到的字符)。这通常是不必要的(通过明确清除IFS可以产生相同的效果,如while IFS= read -r line; do ...),但由于目标是可重现的,我们正在做正确的事。 :)

遵循这些惯例,您将看到符合POSIX sh的所有shell之间的一致行为。 (唯一不符合POSIX sh的主要shell - 默认情况下,在认为标准强制行为不合理的地方违反兼容性 - 是zsh)。

答案 1 :(得分:0)

你提到echo。你写的是

吗?
echo $multiLineVar

echo "$multiLineVar"

在第一种情况下,shell会将嵌入的换行视为分隔单词的空格,因此echo永远不会看到它们。

答案 2 :(得分:0)

简单的方法是使用while循环,如下所示

filename=/path/to/file/file.txt
while read variablename

do echo "$variablename" done < "filename" 它的作用是读取整行直到\ n