2009-10-30 8 views
6

テキストファイルのディレクトリをループして1つのドキュメントに結合しようとしています。これは素晴らしいですが、テキストファイルにはコードスニペットが含まれており、すべての書式設定が左に折りたたまれています。行の先頭の空白はすべて取り除かれます。読み込み中に白い空白を保持する>> bashの行ごとにファイルを書き込む

#!/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 noobですが、高低を検索した後、適切な解決策を見つけることができませんでした。明らかにBASHは、一般的な主要な空白を嫌っています。

答えて

3

の代わりに:(あなたがラインで物事ラインを実行する必要があり理由がある場合、問題のことを含めて良いと思います。)

cat $f >>$OUTPUT 

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

これを行ってください

+0

これも空白を抹消します。私は、それが私に先導的なスペースを節約するためのより多くのオプションを与えるかどうかを見るために行ごとに切り替えました。 –

+1

それは空白を殺しません。ありがとう男:> –

+1

面白いです。この回答は、説明なしで2回下降しています。あなたがdownvoteに行くなら、なぜ言う。 (そして、それがあなたが「これはちょうど1つのcatコマンドかもしれない」と思っているからです:1.本当に、ファイルと2の間に挿入された余分な空白行を書き留めておいてください。簡単にするために、実際のバージョンにはファイルごとにロジックが追加されるかもしれません)。 –

3

これは、ファイルを結合するには非常に高価な方法です。

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 
+0

あなたは1秒で私を打つ。 –

+1

nice。ありがとうございました。私はBashが概念的に大好きです。今私は自分の知識を私の愛情と一致させる必要があります。乾杯。 –

+0

私の書類のタイトルは、皮肉なものです。heh –

1

これは、あなたは、各入力間の改行を散在することができます元のスクリプトで実行したのと同じです:

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

$FILESは、これが機能するようには引用されていないことに注意してください(それ以外の場合は、出力の最後に改行が1回しか表示されません)が、ファイル名のスペースを保護するためにはを引用符で囲む必要があります。

40

他の人が指摘しているように、読み込みエコーループの代わりにcatまたはawkを使用する方がはるかに良い方法です。空白トリミングの問題(およびあなたが遭遇しなかった他のいくつかの問題)より速く走り、少なくとも猫では、よりクリーンなコードです。それにもかかわらず、私は読み込みエコーループを正しく動作させるために挑戦したいと思います。

まず、ホワイトスペーストリミングの問題:readコマンドは、先頭と末尾の空白を自動的に切り詰めます。これは、IFS変数を空白に設定することによって空白の定義を変更することで修正できます。また、readは、行末のバックスラッシュは次の行が継続行であることを意味し、この行と一緒にスプライスする必要があります。これを修正するには、-r(生)フラグを使用します。 3番目の問題は、エコーの多くの実装が文字列のエスケープシーケンスを解釈することです(例えば、\ nが実際の改行に変わる可能性があります)。これを修正するには、代わりにprintfを使用してください。最後に、一般的なスクリプティングの衛生ルールと同じように、実際には必要ないときはcatを使用しないでください。代わりに入力リダイレクトを使用してください。これらの変更により、内側のループは次のようになります。

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がありますtime through(つまり、最後には最後の.textileファイルのみが含まれます)。これをループの前に移動する必要があります。ファイルの先頭に空白行を1つ入れたり、ファイルの間に3つの空白行(最初と最後の2つ)を入れるのがここで意図しているのかどうかはわかりません。適切な交換が行われます。 、

#!/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 
+0

このゴードンに時間を入れていただき、ありがとうございます。 –

+0

素晴らしい、これのために全部を見た、ありがとう –

+0

ベスト答えはここに!あまりにもはっきりと説明する時間をとってくれてありがとう。 :) – Arnlen

0

正解、芋、thisです以下に再現:とにかく、ここで私がアップして、これらの問題のすべてを固定した後ことができるものだ、それは状況の世話をしますということ

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 
関連する問題