Perintah Linux untuk menyatukan file ke dirinya sendiri n kali

31

Saya telah mengambil buku file teks biasa dari Project Gutenberg (sekitar 0,5MB) yang ingin saya gabungkan ke nwaktu itu sendiri untuk menghasilkan file teks besar yang saya bisa patokan beberapa algoritma. Apakah ada perintah linux yang dapat saya gunakan untuk mencapai ini? catkedengarannya ideal, tetapi tampaknya tidak bermain terlalu baik dengan menggabungkan file ke dirinya sendiri, ditambah tidak secara langsung mengatasi nwaktu bagian dari pertanyaan.

Bryce Thomas
sumber
2
menggunakan semacam loop, dan menambahkan? jadi ulangi foo.txt >> bar.txt dan bungkus itu dalam sesuatu yang akan menjalankan perintah itu berkali-kali?
Journeyman Geek

Jawaban:

35

Dua bagian untuk ini, bagi saya - pertama - untuk menggunakan cat untuk menampilkan file teks ke output standar, dan menggunakan append untuk menambahkannya ke file lain - misalnya foo.txt >> bar.txt akan menambahkan foo.txt ke bar.txt

lalu jalankan n kali dengan

for i in {1..n};do cat foo.txt >> bar.txt; done

mengganti n pada perintah itu dengan nomor Anda

harus bekerja, di mana n adalah nomor Anda

Jika Anda menggunakan csh, ada perintah 'ulangi'.

ulangi bagian terkait jawaban yang disalin dari sini , dan saya mengujinya pada sistem ubuntu 11.04 pada bash shell default.

Journeyman Geek
sumber
3
Fakta menyenangkan: ini sebenarnya berfungsi tanpa mengganti 'n', dalam hal ini ia akan mengeksekusi tubuh satu kali untuk setiap karakter antara ASCII '1' dan ASCII 'n' (jadi 62 kali). Tetapi {1..12}dengan benar akan menjalankan tubuh 12 kali.
Arnout Engelen
1
Anda mungkin ingin mengarahkan ulang seluruh saluran pipa, daripada menambahkannya di setiap iterasi:for i in {1..n};do cat foo.txt; done > bar.txt
Toby Speight
2

Saya bosan jadi di sini ada beberapa metode tentang cara menggabungkan file untuk dirinya sendiri, kebanyakan dengan headsebagai penopang. Maafkan saya jika saya menjelaskan sendiri, saya hanya suka mengatakan hal-hal: P


Dengan asumsi Nadalah jumlah rangkaian diri yang ingin Anda lakukan dan bahwa file Anda dinamai file.

Variabel:

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)

Diberikan salinan yang filedipanggil file2, total_repeatsadalah berapa kali fileperlu ditambahkan file2untuk membuatnya sama seperti jika filedigabungkan ke Nwaktu itu sendiri .

Kata MATH ada di sini, kurang lebih: MATH (inti)

Ini hal ilmu komputer semester pertama tapi sudah lama sejak saya melakukan bukti induksi sehingga saya tidak bisa mengatasinya ... (juga kelas rekursi ini cukup terkenal 2^Loopssehingga ada juga ....)


POSIX

Saya menggunakan beberapa hal non-posix tetapi mereka tidak penting. Untuk tujuan saya:

 yes() { while true; do echo "$1"; done; }

Oh, saya hanya menggunakan itu. Oh well, bagian itu sudah ada di sini ...


Metode


head dengan pelacakan linecount.

ln=$linecount
for i in $(seq 1 $N); do
    <file head -n $ln >> file;
    ln=$((ln*2))
done

Tidak ada file temp, tidak ada kucing, belum terlalu banyak matematika, semua sukacita.


teedengan MATEMATIKA

<file tee -a file | head -n $total_lines > $tmp
cat $tmp > file

Berikut teeadalah bacaan dari filetetapi terus-menerus menambahkannya, sehingga akan terus membaca file di ulangi sampai headberhenti. Dan kita tahu kapan harus menghentikannya karena MATEMATIKA . Appendenya lewat laut, jadi saya menggunakan file temp. Anda bisa memotong garis berlebih dari fileterlalu.


eval, penguasa kegelapan!

eval "cat $(yes file | head -n $((total_repeats+1)) | tr '\n' ' ')" > $tmp
cat $tmp > file

Ini hanya memperluas cat file file file ...dan mengevaluasinya. Anda juga dapat melakukannya tanpa $tmpfile:

eval "cat $(yes file | head -n $total_repeats | tr '\n' ' ')" |
  head -n $((total_lines-linecount)) >> file

head"Trik" kedua catdengan menempatkan perantara di antara itu dan operasi penulisan. Anda bisa menipu catdengan orang lain catjuga tetapi itu memiliki perilaku yang tidak konsisten. Coba ini:

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

Memaksa seduntuk membaca seluruh file sebagai satu baris, menangkap semua file, lalu menempelkannya $total_repeatsbeberapa kali.

Tentu saja ini akan gagal jika Anda memiliki karakter nol di file Anda. Pilih satu yang Anda tahu tidak ada di sana.

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
}

Itu saja untuk sekarang para pemuda, saya harap jawaban sewenang-wenang ini tidak mengganggu siapa pun. Saya menguji mereka semua berkali-kali tapi saya hanya pengguna shell dua tahun jadi ingatlah itu saya kira. Sekarang tidur ...

rm $tmp

phicr
sumber
2

Anda tentu bisa menggunakan catini:

$ cat /tmp/f
foo
$ cat /tmp/foo /tmp/f
foo
foo

Untuk mendapatkan $nsalinan, Anda dapat menggunakan yespipa ke head -n $n:

$ yes /tmp/f | head -n 10
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f
/tmp/f

Menyatukan itu memberi

yes /tmp/f | head -n $n | xargs cat >/tmp/output
Toby Speight
sumber