Estou entediado, então aqui estão mais alguns métodos sobre como concatenar um arquivo para si mesmo, principalmente com headuma muleta. Perdoe-me se eu me explicar demais, eu apenas gosto de dizer coisas: P
Supondo que Nseja o número de concatenações automáticas que você deseja fazer e que seu arquivo seja nomeado file.
Variáveis:
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 uma cópia do filechamado file2, total_repeatsé o número de vezes que fileseria necessário adicionar file2para torná-lo o mesmo que se filefosse concatenado para si próprio Nvezes.
Disse MATH está aqui, mais ou menos: MATH (essência)
É o primeiro semestre de ciência da computação, mas já faz um tempo desde que eu fiz uma prova de indução, para que eu não possa superar isso ... (também essa classe de recursão é bem conhecida por existir, 2^Loopstambém existe ...)
POSIX
Eu uso algumas coisas não-posix, mas elas não são essenciais. Para meus propósitos:
yes() { while true; do echo "$1"; done; }
Ah, eu só usei isso. Oh bem, a seção já está aqui ...
Métodos
head com rastreamento de contagem de linha.
ln=$linecount
for i in $(seq 1 $N); do
<file head -n $ln >> file;
ln=$((ln*2))
done
Nenhum arquivo temporário, nenhum gato, nem mesmo muita matemática, toda alegria.
teecom MATEMÁTICA
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Aqui teeestá a leitura, filemas sempre anexada a ele, para que continue lendo o arquivo repetidamente até headparar. E sabemos quando parar por causa da MATEMÁTICA . O anexo é exagerado, então usei um arquivo temporário. Você também pode cortar o excesso de linhas file.
eval, o senhor das trevas!
eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file
Isso apenas se expande cat file file file ...e avalia. Você pode fazer isso sem o $tmparquivo também:
eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
head -n $((total_lines-linecount)) >> file
O segundo head"truques" cat, colocando um intermediário entre ele e a operação de gravação. Você também pode enganar catcom outro cat, mas isso tem um comportamento inconsistente. Tente o seguinte:
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
Força seda leitura do arquivo inteiro como uma linha, captura tudo e cola-o $total_repeatsvárias vezes.
Obviamente, isso falhará se você tiver caracteres nulos no seu arquivo. Escolha uma que você sabe que não está lá.
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
}
Por enquanto é isso pessoal, espero que essa resposta arbitrária não incomode ninguém. Eu testei todos eles várias vezes, mas sou apenas um usuário de shell de dois anos, então lembre-se disso. Agora para dormir ...
rm $tmp