Penyortiran unik: Redirect output ke file yang sama

14

Apakah ada cara singkat untuk menyimpan output pipa ke file yang sama yang sedang diproses. Sebagai contoh, inilah yang sebenarnya saya lakukan

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

Saya bertanya-tanya apakah ada cara untuk melakukannya hanya dalam satu baris (tidak menambahkan perintah-perintah itu menggunakan &&)

Ini bukan caranya, tetapi untuk mendapatkan ide

$ cat filename | sort | uniq > filename
whitenoisedb
sumber
2
echo $(cat filename | sort | uniq > result) > filenameatau sesuatu ? Hanya lewat, saya tidak punya waktu untuk mencobanya.
MrVaykadji

Jawaban:

18

Anda dapat menggunakan spongedari paket moreutils :

LC_ALL=C sort -u filename | sponge filename

Anda juga tidak perlu menggunakan pipa uniq, karena ketika sortmemiliki -uopsi untuk garis unik saat menyortir.

Perhatikan bahwa pada sistem GNU dengan lokal UTF-8, sort -uatau sort | uniqtidak memberi Anda garis unik, tetapi yang pertama dari urutan garis yang mengurutkan yang sama di lokal saat ini.

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

hanya memberimu . Mengubah lokal ke C memaksa urutan penyortiran berdasarkan nilai byte:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq

cuonglm
sumber
12

Anda tidak memerlukan perintah tambahan seperti catdan uniqdan juga tanpa menggunakan rmperintah dan mvperintah untuk menghapus dan mengganti nama file. cukup gunakan perintah sederhana.

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

Bagaimana cara kerjanya?

sortPerintah mengurutkan nama file Anda dan dengan -uopsi, menghapus garis duplikat dari itu. kemudian dengan -oopsi tulis output ke file yang sama dengan metode in place.

αғsнιη
sumber
3
Jika sistem macet saat sortberjalan, Anda akan kehilangan file asli Anda.
cuonglm
@ Gnouc Jadi, ini akhir dari sial !! : '(
αғsнιη
1
Terima kasih! dalam contoh ini, dengan ´sort´ khususnya, saya harus melakukan itu. Namun saya berpikir tentang kasus umum. @ Gnouc, haha ​​tidak ada cara untuk berpikir bahwa jika itu tidak terjadi pada Anda, kan?
whitenoisedb
3

Contoh yang Anda sarankan (di bawah) tidak berfungsi karena Anda sebenarnya akan membaca dan menulis ke file yang sama secara bersamaan.

$ cat filename | sort | uniq > filename

Gagasan dengan pipa atau pengalihan adalah bahwa perintah di sisi kiri dan kanan setiap pipa atau pengalihan berjalan secara bersamaan, secara paralel. Perintah di sebelah kanan memproses informasi saat diserahkan dari perintah di sebelah kiri, sementara perintah di sebelah kiri masih berjalan.

Agar skenario Anda berfungsi, perintah yang membaca dari file harus selesai sebelum perintah yang menulis ke file dimulai. Agar ini berfungsi, Anda harus mengarahkan output ke lokasi sementara terlebih dahulu, kemudian setelah selesai, kirim kembali dari lokasi sementara kembali ke file.

Cara yang lebih baik untuk melakukan ini pada dasarnya adalah seperti pada contoh sebelumnya, di mana Anda mengarahkan ulang ke file sementara kemudian mengganti nama file itu kembali ke aslinya (kecuali bahwa Anda tidak perlu menghapus file terlebih dahulu, karena memindahkan menghapus target yang ada) .

$ cat filename | sort | uniq > result
$ mv -f result filename

Anda juga bisa menyimpannya ke dalam variabel string, kecuali itu hanya berfungsi ketika data cukup kecil untuk semua dapat disimpan dalam memori sekaligus.

thomasrutter
sumber
Saat seseorang mengeluarkan suntingan yang disarankan, Anda dapat mengubahnya cat filename | sortmenjadi adil sort filename- cattidak perlu di sini.
thomasrutter
Contoh saya di bawah ini bukan cara untuk melakukannya. Terima kasih atas klarifikasi. catmungkin tidak perlu dalam kasus ini tetapi saya fokus pada bagian pengalihan.
whitenoisedb
1
Saya sedang menjelaskan mengapa contoh Anda di bawah ini tidak berfungsi. Saya tahu Anda tahu itu tidak berhasil.
thomasrutter
Terima kasih telah mengklarifikasi! Sebenarnya saya tidak tahu apa yang sebenarnya terjadi.
whitenoisedb
2

Anda dapat menggunakan teeperintah:

sort -u filename | tee filename > /dev/null

The teeperintah membaca dari input standar dan menulis ke output standar dan file.

Sylvain Pineau
sumber
2
Ini tidak bekerja untuk saya.
pjvandehaar
3
Ini tidak berfungsi askubuntu.com/a/752451
Steven Penny
Ini tidak bekerja untuk saya. misalnya, untuk memindahkan baris ke bagian bawah file: (cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/nullberfungsi. Seperti pos asli, ini tidak berfungsi jika Anda hanya > ~/filetanpa tee. Tee tampaknya serupa di sini sort -o file, yang menulis ke file bernama tanpa melanjutkan pipa yang sama.
Joshua Goldberg
Tunggu, maaf! Saya telah melihat secara empiris ini akan kehilangan data yang tidak terduga seperti dijelaskan dalam tautan dari @Steven. Buat file dengan angka 1..9 pada 9 baris. Berikut ini akan berfungsi beberapa kali, dan kemudian sesekali menghapus semua data dari file: (cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x Saya merekomendasikan file temp dan mvatau mungkin solusi dari tautan @ Steven.
Joshua Goldberg
@ JoshuaGoldberg, sudahkah Anda melihat jawaban saya di halaman ini?
Steven Penny
0

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc 'sort u|x' filename
  1. sort u semacam unik

  2. x tulis jika ada perubahan (sudah) dan berhenti

Steven Penny
sumber