Estoy aburrido, así que aquí hay algunos métodos más sobre cómo concatenar un archivo consigo mismo, principalmente con head
una muleta. Disculpe si me explico demasiado, solo me gusta decir cosas: P
Suponiendo que N
es 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 file
llamado file2
, total_repeats
es el número de veces file
que debería agregarse file2
para que sea igual que si file
estuviera 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^Loops
tambié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.
tee
con MATEMÁTICAS
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Aquí tee
está leyendo, file
pero añadiéndole perpetuamente, por lo que seguirá leyendo el archivo repetidamente hasta que lo head
detenga. 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 $tmp
archivo:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
El segundo head
"truco" cat
al poner a un intermediario entre este y la operación de escritura. También podrías engañar cat
a 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 sed
a leer todo el archivo como una línea, captura todo y luego lo pega $total_repeats
varias 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