Estoy aburrido, así que aquí hay algunos métodos más sobre cómo concatenar un archivo consigo mismo, principalmente con headuna muleta. Disculpe si me explico demasiado, solo me gusta decir cosas: P
Suponiendo que Nes el número de autoconcatenaciones que desea hacer y que su archivo tiene un nombre file.
Variables:
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)
Dada una copia de filellamado file2, total_repeatses el número de veces fileque debería agregarse file2para que sea igual que si fileestuviera concatenado a sí mismo N.
Dicho MATH está aquí, más o menos: MATH (esencia)
Es material de informática del primer semestre, pero ha pasado un tiempo desde que hice una prueba de inducción, así que no puedo superarlo ... (también se sabe que esta clase de recursión es así que 2^Loopstambién existe ...)
POSIX
Utilizo algunas cosas que no son posix pero no son esenciales. Para mis propósitos:
yes() { while true; do echo "$1"; done; }
Oh, solo usé eso. Oh bueno, la sección ya está aquí ...
Métodos
head con seguimiento de recuento de líneas.
ln=$linecount
for i in $(seq 1 $N); do
<file head -n $ln >> file;
ln=$((ln*2))
done
Sin archivo temporal, sin gato, ni siquiera demasiadas matemáticas, toda alegría.
teecon MATEMÁTICAS
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Aquí teeestá leyendo, filepero añadiéndole perpetuamente, por lo que seguirá leyendo el archivo repetidamente hasta que lo headdetenga. Y sabemos cuándo detenerlo debido a MATH . El anexo va por la borda, así que utilicé un archivo temporal. También podría recortar el exceso de líneas file.
eval, el señor de la oscuridad!
eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file
Esto solo se expande cat file file file ...y lo evalúa. También puedes hacerlo sin el $tmparchivo:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
El segundo head"truco" catal poner a un intermediario entre este y la operación de escritura. También podrías engañar cata otro cat, pero eso tiene un comportamiento inconsistente. Prueba esto:
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
Obliga seda leer todo el archivo como una línea, captura todo y luego lo pega $total_repeatsvarias veces.
Por supuesto, esto fallará si tiene caracteres nulos en su archivo. Elige uno que sabes que no está allí.
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
}
Eso es todo por ahora muchachos, espero que esta respuesta arbitraria no moleste a nadie. Los probé muchas veces, pero solo soy un usuario de shell de dos años, así que tenlo en cuenta, supongo. Ahora a dormir...
rm $tmp