Sono annoiato, quindi ecco alcuni altri metodi su come concatenare un file a se stesso, principalmente con headuna stampella. Scusatemi se mi spiego troppo, mi piace solo dire cose: P
Supponendo Nè il numero di auto-concatenazioni che si desidera eseguire e che il file sia denominato file.
variabili:
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)
Data una copia di filechiamato file2, total_repeatsè il numero di volte fileche dovrebbe essere aggiunto file2per renderlo uguale a se filefosse concatenato a se stesso N.
Detto MATH è qui, più o meno: MATH (sintesi)
È roba di informatica del primo semestre ma è passato un po 'di tempo da quando ho fatto una prova di induzione quindi non riesco a superarla ... (anche questa classe di ricorsione è abbastanza conosciuta per esserci, 2^Loopsquindi c'è anche quella ....)
POSIX
Uso alcune cose non posix ma non sono essenziali. Per i miei scopi:
yes() { while true; do echo "$1"; done; }
Oh, l'ho solo usato. Vabbè, la sezione è già qui ...
metodi
head con tracciamento linecount.
ln=$linecount
for i in $(seq 1 $N); do
<file head -n $ln >> file;
ln=$((ln*2))
done
Nessun file temporaneo, nessun gatto, nemmeno troppa matematica, tutta gioia.
teecon MATH
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Qui teesta leggendo filema accodando perpetuamente ad esso, quindi continuerà a leggere il file ripetuto fino a quando headnon lo interrompe. E sappiamo quando fermarlo a causa di MATH . L'aggiunta va in mare, quindi ho usato un file temporaneo. Potresti anche tagliare le linee in eccesso file.
eval, il signore delle tenebre!
eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file
Questo si espande cat file file file ...e lo eleva. Puoi farlo anche senza il $tmpfile:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
Il secondo head"trucchi" catmettendo un intermediario tra esso e l'operazione di scrittura. Potresti ingannare anche catun altro catma questo ha un comportamento incoerente. Prova questo:
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
Forza la sedlettura dell'intero file come una riga, lo cattura tutto, quindi lo incolla il $total_repeatsnumero di volte.
Questo ovviamente fallirà se nel tuo file sono presenti caratteri null. Scegline uno che sai che non c'è.
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
}
Questo è tutto per ora ragazzi, spero che questa risposta arbitraria non abbia disturbato nessuno. Ho provato tutti loro molte volte, ma sono solo un utente della shell di due anni, quindi tienilo a mente, suppongo. Adesso a dormire ...
rm $tmp