正如其他人指出的那样,使用 cat 或 awk 而不是 read-echo 循环是一种更好的方法 - 避免空格修剪问题(以及您没有偶然发现的其他几个问题),运行速度更快,至少对于 cat,代码更简洁。尽管如此,我还是想尝试一下让 read-echo 循环正常工作。
首先,空白修剪问题:read 命令自动修剪前导和尾随空白;这可以通过将 IFS 变量设置为空白来更改其空白定义来解决。此外, read 假设行尾的反斜杠表示下一行是续行,应该与这一行拼接在一起;要解决此问题,请使用其 -r (原始)标志。这里的第三个问题是许多 echo 实现解释字符串中的转义序列(例如,它们可能将 \n 变成实际的换行符);要解决此问题,请改用 printf。最后,就像一般的脚本卫生规则一样,当你实际上不需要时,你不应该使用 cat ;改用输入重定向。通过这些更改,内部循环如下所示:
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f
...周围的脚本还有一些其他问题:尝试将 FILES 定义为可用 .textile 文件列表的行在其周围有引号,这意味着它永远不会扩展为实际的文件列表。最好的方法是使用数组:
FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"
(并且所有出现的 $f 都应该用双引号括起来,以防任何文件名中包含空格或其他有趣的字符 - 也应该使用 $OUTPUT 来执行此操作,尽管因为这是在脚本中定义的,所以它实际上是安全的离开。)
最后,echo "">$OUTPUT
在循环文件的顶部附近有一个每次通过都会擦除输出文件(即最后,它只包含最后一个 .textile 文件);这需要移到循环之前。我不确定这里的意图是在文件开头放置一个空行,还是在文件之间放置三个空行(开头一个,结尾两个),所以我不确定到底是什么适当的替换是。无论如何,这是我在解决所有这些问题后可以解决的问题:
#!/bin/sh
OUTPUT="../best_practices.textile"
FILES=(../best-practices/*.textile)
: >"$OUTPUT"
for f in "${FILES[@]}"
do
echo "Processing $f file..."
echo >>"$OUTPUT"
while IFS='' read -r line; do
printf "%s\n" "$line">>"$OUTPUT"
done <"$f"
echo >>"$OUTPUT"
echo >>"$OUTPUT"
done