Sono annoiato, quindi ecco alcuni altri metodi su come concatenare un file a se stesso, principalmente con head
una 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 file
chiamato file2
, total_repeats
è il numero di volte file
che dovrebbe essere aggiunto file2
per renderlo uguale a se file
fosse 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^Loops
quindi 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.
tee
con MATH
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Qui tee
sta leggendo file
ma accodando perpetuamente ad esso, quindi continuerà a leggere il file ripetuto fino a quando head
non 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 $tmp
file:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
Il secondo head
"trucchi" cat
mettendo un intermediario tra esso e l'operazione di scrittura. Potresti ingannare anche cat
un altro cat
ma 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 sed
lettura dell'intero file come una riga, lo cattura tutto, quindi lo incolla il $total_repeats
numero 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