Saya yakin saya pernah menemukan perintah unix yang dapat mencetak baris umum dari dua atau lebih file, apakah ada yang tahu namanya? Itu jauh lebih sederhana daripada diff
.
unix
shell
command-line
terlalu banyak php
sumber
sumber
comm
memerlukan file input yang diurutkan. Jika Anda ingin hanya baris demi baris yang umum, itu bagus. Tetapi jika Anda menginginkan apa yang saya sebut "anti-diff",comm
tidak melakukan pekerjaan.pr-123-xy-45
dan file2 berisiec11_orop_pr-123-xy-45.gz
. Saya perlu file3 mengandungec11_orop_pr-123-xy-45.gz
Jawaban:
Perintah yang Anda cari adalah
comm
. misalnya:-Sini:
-1 : tekan kolom 1 (baris unik ke 1.sorted.txt)
-2 : tekan kolom 2 (baris unik ke 2.sorted.txt)
sumber
grep
melakukan beberapa hal aneh yang mungkin tidak Anda harapkan. Secara khusus, semua yang ada di1.txt
dalamnya akan ditafsirkan sebagai ekspresi reguler dan bukan string biasa. Selain itu, setiap baris kosong di1.txt
akan cocok dengan semua baris di2.txt
. Jadigrep
hanya akan bekerja dalam situasi yang sangat spesifik. Anda setidaknya ingin menggunakanfgrep
(ataugrep -f
) tetapi hal yang kosong mungkin akan mendatangkan malapetaka pada proses ini.grep -F -x -f file1 file2
comm
perintah menjadi 3 file terpisah? Jawabannya terlalu besar untuk cocok dengan nyaman di sini.Untuk dengan mudah menerapkan perintah comm ke file yang tidak disortir , gunakan subtitusi proses Bash :
Jadi file abc dan def memiliki satu baris yang sama, yang dengan "132". Menggunakan comm pada file yang tidak disortir:
Baris terakhir tidak menghasilkan output, baris umum tidak ditemukan.
Sekarang gunakan comm pada file yang diurutkan, mengurutkan file dengan proses substitusi:
Sekarang kami dapat jalur 132!
sumber
sort abc > abc.sorted
,sort dev > def.sorted
lalucomm -12 abc.sorted def.sorted
?Untuk melengkapi Perl one-liner, inilah
awk
persamaannya:Ini akan membaca semua baris dari
file1
dalam arrayarr[]
, dan kemudian memeriksa setiap barisfile2
jika sudah ada dalam array (yaitufile1
). Garis-garis yang ditemukan akan dicetak sesuai urutan kemunculannyafile2
. Perhatikan bahwa perbandinganin arr
menggunakan seluruh baris darifile2
sebagai indeks ke array, sehingga hanya akan melaporkan kecocokan tepat pada seluruh baris.sumber
perl
yang lain, karena). Terima kasih satu juta, NonaMungkin maksud Anda
comm
?Rahasia dalam menemukan informasi ini adalah halaman info. Untuk program GNU, mereka jauh lebih detail daripada halaman manualnya. Coba
info coreutils
dan itu akan mencantumkan Anda semua utilitas kecil yang bermanfaat.sumber
Sementara
memberi Anda perbedaan dua file (apa yang ada di 2.txt dan bukan di 1.txt), Anda dapat dengan mudah melakukan a
untuk mengumpulkan semua jalur umum, yang seharusnya memberikan solusi mudah untuk masalah Anda. Jika Anda memiliki file yang diurutkan, Anda harus mengambil
comm
. Salam!sumber
grep
melakukan beberapa hal aneh yang mungkin tidak Anda harapkan. Secara khusus, semua yang ada di1.txt
dalamnya akan ditafsirkan sebagai ekspresi reguler dan bukan string biasa. Selain itu, setiap baris kosong di1.txt
akan cocok dengan semua baris di2.txt
. Jadi ini hanya akan bekerja dalam situasi yang sangat spesifik.grep
notasi POSIX , yang didukung oleh yanggrep
ditemukan pada sebagian besar varian Unix modern. Tambahkan-F
(atau gunakanfgrep
) untuk menekan ekspresi reguler. Tambahkan-x
(tepatnya) agar hanya cocok dengan seluruh baris.comm
file yang diurutkan?comm
dapat bekerja dengan file besar yang sewenang-wenang selama mereka disortir karena hanya perlu menyimpan tiga baris dalam memori (Saya kira GNUcomm
bahkan akan tahu untuk menyimpan awalan hanya jika garisnya benar-benar panjang). Thegrep
solusi perlu menjaga semua ekspresi pencarian di memori.Jika kedua file belum diurutkan, Anda dapat menggunakan:
dan itu akan berhasil, menghindari pesan kesalahan
comm: file 2 is not in sorted order
saat melakukancomm -12 a.txt b.txt
.sumber
<(command)
tidak portabel untuk shell POSIX, meskipun bekerja di Bash dan beberapa lainnya.sumber
comm
perintah karena mencari setiap barisfile1
difile2
manacomm
hanya akan membandingkan jika barisn
difile1
yaitu sama dengan garisn
difile2
.comm
tidak hanya membandingkan baris N di file1 dengan baris N di file2. Ia dapat dengan baik mengelola serangkaian baris yang disisipkan dalam file mana pun (yang setara dengan menghapus serangkaian baris dari file lain, tentu saja). Itu hanya membutuhkan input untuk diurutkan.comm
jawaban jika seseorang ingin menjaga ketertiban. Lebih baik daripadaawk
menjawab jika seseorang tidak ingin duplikat.sumber
Pada versi Linux yang terbatas (seperti QNAP (nas) yang saya kerjakan):
grep -f file1 file2
dapat menyebabkan beberapa masalah seperti yang dikatakan oleh @ChristopherSchultz dan penggunaannyagrep -F -f file1 file2
sangat lambat (lebih dari 5 menit - belum selesai - lebih dari 2-3 detik dengan metode di bawah ini pada file di atas 20MB)Jadi inilah yang saya lakukan:
Jika
files.same.sorted
harus dalam urutan yang sama dari yang asli, daripada tambahkan baris ini untuk urutan yang sama dari file1:atau, untuk urutan yang sama dari file2:
sumber
Hanya untuk referensi jika seseorang masih mencari cara melakukan ini untuk banyak file, lihat jawaban tertaut untuk Menemukan garis yang cocok di banyak file.
Menggabungkan dua jawaban ini ( ans1 dan ans2 ), saya pikir Anda bisa mendapatkan hasil yang Anda butuhkan tanpa mengurutkan file:
Cukup simpan, berikan hak eksekusi (
chmod +x compareFiles.sh
), dan jalankan. Ini akan mengambil semua file yang ada di direktori kerja saat ini dan akan membuat perbandingan semua-vs-semua meninggalkan dalam file "matching_lines" hasilnya.Hal-hal yang harus diperbaiki:
sumber
Ini harus dilakukan.
sumber
rm -f file3.txt
jika Anda akan menghapus file; itu tidak akan melaporkan kesalahan jika file tidak ada. OTOH, itu tidak perlu jika skrip Anda hanya menggema ke output standar, membiarkan pengguna skrip memilih ke mana output harus pergi. Pada akhirnya, Anda mungkin ingin menggunakan$1
dan$2
(argumen baris perintah) alih-alih nama file yang tetap (file1.out
danfile2.out
). Itu meninggalkan algoritme: itu akan lambat. Ini akan dibacafile2.out
satu kali untuk setiap barisfile1.out
. Ini akan lambat jika file besar (katakanlah beberapa kilobyte).grep -F
yang membaca satu file ke dalam memori dan kemudian melakukan satu melewati yang lain menghindari berulang kali berulang-ulang di kedua file input.