Nudzę się, więc oto kilka innych metod łączenia pliku z samym sobą, głównie head
za pomocą kuli. Wybacz mi, jeśli się nadmiernie tłumaczę, po prostu lubię mówić: P
Zakładając, N
że liczba samopodatków, które chcesz wykonać, i że Twój plik ma nazwę file
.
Zmienne:
linecount=$(<file wc -l)
total_repeats=$(echo "2^$N - 1" | bc) # obtained through the power of MATH
total_lines=$((linecount*(total_repeats+1)))
tmp=$(mktemp --suffix .concat.self)
Biorąc pod uwagę kopię file
wywołanego file2
, należy podać total_repeats
liczbę razy file
, file2
aby była taka sama, jak gdyby file
była połączona z N
czasami.
Mówi się, że MATH jest tutaj mniej więcej: MATH (sedno)
To jest informatyka z pierwszego semestru, ale minęło trochę czasu, odkąd zrobiłem dowód indukcyjny, więc nie mogę się z tym pogodzić ... (również ta klasa rekurencji jest dość dobrze znana, 2^Loops
więc też ...)
POSIX
Używam kilku rzeczy, które nie są posiksowane, ale nie są one niezbędne. Do moich celów:
yes() { while true; do echo "$1"; done; }
Och, użyłem tylko tego. No cóż, sekcja jest już tutaj ...
Metody
head
ze śledzeniem liczby linii.
ln=$linecount
for i in $(seq 1 $N); do
<file head -n $ln >> file;
ln=$((ln*2))
done
Bez pliku tymczasowego, bez kota, jeszcze za dużo matematyki, cała radość.
tee
z MATH
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Tutaj tee
jest czytanie ze file
lecz wiecznie dołączając do niego, więc będzie zachować czytania pliku na powtórzeniu aż head
zatrzymuje ją. I wiemy, kiedy to przerwać z powodu MATH . Dołączanie przesadza, więc użyłem pliku tymczasowego. Możesz również przyciąć nadmiar linii file
.
eval
władca ciemności!
eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file
To po prostu rozszerza się cat file file file ...
i ewaluuje. Możesz to zrobić również bez $tmp
pliku:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
Drugie head
„triki” cat
polegające na umieszczeniu pośrednika między operacją a operacją zapisu. Możesz też oszukać cat
z innym, cat
ale to ma niespójne zachowanie. Spróbuj tego:
test_double_cat() {
local Expected=0
local Got=0
local R=0
local file="$(mktemp --suffix .double.cat)"
for i in $(seq 1 100); do
printf "" > $file
echo "1" >> $file
echo "2" >> $file
echo "3" >> $file
Expected=$((3*$(<file wc -l)))
cat $file $file | cat >> $file
Got=$(<file wc -l)
[ "$Expected" = "$Got" ] && R="$((R+1))"
done
echo "Got it right $R/100"
rm $file
}
sed
:
<file tr '\n' '\0' |
sed -e "s/.*/$(yes '\0' | head -n $total_repeats | tr -d '\n')/g" |
tr '\0' '\n' >> file
Zmusza sed
do odczytania całego pliku jako linii, przechwytuje go, a następnie wkleja $total_repeats
wiele razy.
Nie powiedzie się to oczywiście, jeśli w pliku są znaki o wartości NULL. Wybierz taki, o którym wiesz, że go nie ma.
find_missing_char() {
local file="${1:-/dev/stdin}"
firstbyte="$(<$file fold -w1 | od -An -tuC | sort -un | head -n 1)"
if [ ! "$firstbyte" = "0" ]; then
echo "\0"
else
printf "\\$(printf '%03o\t' $((firstbyte-1)) )"
fi
}
To wszystko na razie chłopaki, mam nadzieję, że ta arbitralna odpowiedź nikomu nie przeszkadzała. Testowałem je wszystkie wiele razy, ale jestem tylko dwuletnim użytkownikiem powłoki, więc myślę, że o tym myślę. Teraz spać ...
rm $tmp