保留前导空格在阅读>>通过在bash线写一个文件中的行(Preserving leadi

2019-09-02 11:56发布

我通过文本文件的目录试图环和它们合并成一个文件。 这个伟大的工程,但文本文件中包含的代码片段,以及我所有的格式是越来越晕倒在左边。 在一条线上的所有领先的空白被剥离。

#!/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讨厌一般领先的空白。

Answer 1:

代替:

cat $f | while read line; do 
    echo "$line">>$OUTPUT
done

做这个:

cat $f >>$OUTPUT

(如果您需要通过线做事线原因,它会是不错的,包括在的问题。)



Answer 2:

正如其他人所指出的那样,使用替代读取 - 回声环猫或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


Answer 3:

这是合并的文件过于昂贵的方式。

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.txt


Answer 4:

这使您可以点缀每个输入文件之间的换行符您在最初的剧本已经完成:

for f in $FILES; do echo -ne '\n\n' | cat "$f" -; done > $OUTPUT

需要注意的是$FILES是不带引号的这个工作(否则额外的新行的所有输出的末尾只出现一次),但$f必须被引用,以保护空间中的文件名,如果存在的话。



Answer 5:

正确的答案,国际海事组织,是这个 ,转载如下:

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


文章来源: Preserving leading white space while reading>>writing a file line by line in bash