Jak podkreślali inni, użycie cat lub awk zamiast pętli read-echo jest o wiele lepszym sposobem - unika problemu z przycinaniem białych znaków (i kilkoma innymi, na które się nie natknąłeś) , działa szybciej, a przynajmniej z kotem, jest po prostu czystszy kod. Niemniej jednak, chciałbym zrobić dźgnięcie, aby pętla read-echo działała poprawnie.
Po pierwsze, problem z przycinaniem białych znaków: polecenie odczytu automatycznie przycina wiodące i końcowe białe znaki; można to naprawić, zmieniając definicję białych znaków, ustawiając zmienną IFS na pustą. Ponadto, read zakłada, że odwrotny ukośnik na końcu linii oznacza, że następna linia jest kontynuacją i powinna być połączona z tą linią; aby to naprawić, użyj flagi -r (raw). Trzeci problem polega na tym, że wiele implementacji echa interpretuje sekwencje specjalne w łańcuchu znaków (np. Mogą one zmienić \ n w rzeczywisty znak nowej linii); aby to naprawić, użyj zamiast tego printf. Na koniec, tak jak w przypadku ogólnej zasady higieny skryptów, nie należy używać kota, gdy nie jest to konieczne; zamiast tego użyj przekierowania wejścia. Z tych zmian, wewnętrzna pętla wygląda następująco:
while IFS='' read -r line; do
printf "%s\n" "$line">>$OUTPUT
done <$f
... istnieją także kilka innych problemów z otaczającej skryptu: linia, która stara się definiować jako pliki z listy dostępnych plików .textile ma cytuje wokół niego, co oznacza, że nigdy nie zostanie rozszerzony na rzeczywistą listę plików.Najlepszym sposobem, aby to zrobić jest użycie tablicy:
FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"
(i wszystkie wystąpienia $ F powinna być w cudzysłów w przypadku żadnej z nazw mieć spacji lub innych znaków zabawne w nich - powinny naprawdę zrób to również za pomocą $ OUTPUT, ale skoro jest to zdefiniowane w skrypcie, to naprawdę bezpiecznie odejść.)
Wreszcie, jest echo "">$OUTPUT
w górnej części plików pętli, które będą kasować plik wyjściowy co time through (tj. na końcu zawiera tylko ostatni plik tekstowy); to musi być przeniesione przed pętlą. Nie jestem pewien, czy celem było umieszczenie pojedynczej pustej linii na początku pliku, czy trzech pustych linii między plikami (i jednego na początku i dwóch na końcu), więc nie jestem pewien co dokładnie odpowiednim zamiennikiem jest. W każdym razie, oto co mogę się z po zamontowaniu wszystkich tych problemów:
#!/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
To również zabija białe znaki. Przełączyłem się na linię po linii, aby zobaczyć, czy może dałoby mi to więcej opcji na zaoszczędzenie przestrzeni wiodącej. –
nie zabija białej przestrzeni. Dzięki człowiek:> –
Interesujące. Ta odpowiedź została dwukrotnie odrzucona bez żadnego wyjaśnienia. Jeśli masz zamiar przegłosować, powiedz dlaczego. (A jeśli to dlatego, że myślisz "to może być tylko jedno polecenie kota": 1. naprawdę nie, zauważ dodatkowe puste linie wstawione między plikami i 2. Zakładam (być może niepoprawnie), że był to skrypt skrócony dla uproszczenia i wersji rzeczywistej może mieć jakąś dodatkową logikę na jeden plik.) –