我正在尝试遍历文本文件的目录,并将它们组合成一个文档。这很有效,但是文本文件包含代码片段,并且我的所有格式都被折叠到左侧。一行上的所有前导空格都会被去掉。
#!/bin/sh
OUTPUT="../best_practices.textile"
FILES="../best-practices/*.textile"
for f in "$FILES"
do
echo "Processing $f file..."
echo "">$OUTPUT
cat $f | while read line; do
echo "$line">>$OUTPUT
done
echo >>$OUTPUT
echo >>$OUTPUT
done诚然,我是一个狂热的新手,但在到处寻找之后,我找不到一个合适的解决方案。显然,BASH在总体上讨厌前导空格。
发布于 2009-10-30 12:54:37
而不是:
cat $f | while read line; do
echo "$line">>$OUTPUT
done执行以下操作:
cat $f >>$OUTPUT(如果有需要逐行处理的原因,最好在问题中包含这一点。)
发布于 2009-10-31 06:45:11
正如其他人所指出的,使用cat或awk而不是read-echo循环是一种更好的方法--避免了空格修剪问题(以及其他一些您没有遇到过的问题),运行速度更快,而且至少使用cat,代码更简洁。尽管如此,我还是想尝试让read-echo循环正常工作。
首先,空格修剪问题: read命令自动修剪前导空格和尾随空格;这个问题可以通过将IFS变量设置为空白来更改其对空格的定义来解决。另外,read假定行尾的反斜杠意味着下一行是连续的,应该与这行拼接在一起;要解决这个问题,请使用它的-r (raw)标志。这里的第三个问题是,许多echo的实现解释字符串中的转义序列(例如,它们可能会将\n转换为实际的换行符);要解决此问题,请使用printf。最后,就像一般的脚本安全规则一样,您不应该在不需要的时候使用cat;而应该使用输入重定向。有了这些更改,内部循环看起来像这样:
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f...there还存在周围脚本的一些其他问题:试图将文件定义为可用.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发布于 2009-10-30 13:28:21
这是一种过于昂贵的组合文件的方式。
cat ../best-practices/*.textile > ../best_practices.textile如果要在连接时向每个文件添加一个空白(换行符),请使用awk
awk 'FNR==1{print "">"out.txt"}{print > "out.txt" }' *.textile或
awk 'FNR==1{print ""}{print}' file* > out.txthttps://stackoverflow.com/questions/1648055
复制相似问题