保留前导空格在阅读>>通过在bash线写一个文件中的行
-
22-07-2019 - |
题
我是通过文本文件的目录试图环和它们合并成一个文件。这个伟大的工程,但文本文件中包含的代码片段,以及我所有的格式是越来越晕倒在左边。上的线的所有前导空白被剥离。
#!/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小白,但寻找高和低后,我无法找到一个妥善的解决办法。显然BASH讨厌一般前导空白。
解决方案
代替:
cat $f | while read line; do
echo "$line">>$OUTPUT
done
这样做:
cat $f >>$OUTPUT
(如果您需要通过线做事线它会是不错的,包括在问题的原因。)
其他提示
正如其他人所指出的那样,使用cat或awk的,而不是读回声环是一种更好的方法来做到这一点 - 避免了空格修剪问题(和其他几个你没有偶然发现)运行速度更快,并至少有猫,简直是干净的代码。尽管如此,我想带刺在获得读回声环工作的权利。
首先,空格修整问题:所述读取命令自动裁剪前缘和后空白;这可以通过由IFS变量设置为空白改变其空白的定义是固定的。此外,阅读假定在该行的末尾反斜杠表示下一行是延续,并应与此一被接合在一起;要解决这个问题,利用其-r(原始)标志。这里的第三个问题是,回波许多实现解释字符串中转义序列(例如它们可以开启\ n为实际的新行);要解决这个问题,用printf代替。最后,只是作为一般的脚本卫生规则,你不应该当你不真正需要使用的猫;使用输入重定向来代替。这些变化,内部循环是这样的:
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f
...也有一对夫妇的其他问题与周围的脚本:试图定义文件作为可用.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
这是组合文件过于昂贵的方式。
cat ../best-practices/*.textile > ../best_practices.textile
如果要用作您连接到添加空白(换行)到每个文件中,使用AWK
awk 'FNR==1{print "">"out.txt"}{print > "out.txt" }' *.textile
OR
awk 'FNR==1{print ""}{print}' file* > out.txt
这可以让你穿插每个输入文件之间的换行符您在最初的剧本已经完成:
for f in $FILES; do echo -ne '\n\n' | cat "$f" -; done > $OUTPUT
请注意$FILES
是不带引号的这个工作(否则额外的新行的所有输出的末尾只出现一次),但$f
必须被引用,以保护空间中的文件名,如果存在的话。
正确答案,伊莫被此时,复制如下:
while IFS= read line; do
check=${line:0:1}
done < file.txt
请注意,它会照顾,其中输入是从另一命令的情况下,而不是只从一个实际的文件。
请注意,还可以简化重定向,如下所示。
#!/bin/bash
OUTPUT="../best_practices.textile"
FILES="../best-practices/*.textile"
for f in "$FILES"
do
echo "Processing $f file..."
{
echo
while IFS= read line; do
echo "$line"
done < $f
echo
echo;
} > $OUTPUT
done