Estou entediado, então aqui estão mais alguns métodos sobre como concatenar um arquivo para si mesmo, principalmente com head
uma muleta. Perdoe-me se eu me explicar demais, eu apenas gosto de dizer coisas: P
Supondo que N
seja 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 file
chamado file2
, total_repeats
é o número de vezes que file
seria necessário adicionar file2
para torná-lo o mesmo que se file
fosse concatenado para si próprio N
vezes.
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^Loops
també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.
tee
com MATEMÁTICA
<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file
Aqui tee
está a leitura, file
mas sempre anexada a ele, para que continue lendo o arquivo repetidamente até head
parar. 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 $tmp
arquivo 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 cat
com 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 sed
a leitura do arquivo inteiro como uma linha, captura tudo e cola-o $total_repeats
vá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