hapus baris yang lebih baru dari tanggal yang diberikan dalam file

8

Saya terjebak pada bagaimana saya bisa menghapus garis yang lebih baru dari tanggal yang ditentukan. Berikut adalah cuplikan dari isi file.

buildsave.txt

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Saya ingin menghapus garis yang lebih baru dari 2013/12/03 hanya menyisakan

647919 2013/11/30
647946 2013/11/30
647955 2013/12/01

Bagaimana ini bisa dilakukan melalui bash?

Jason G
sumber

Jawaban:

4

Jika sistem Anda menyertakan versi GNU dari dateperintah, Anda bisa menggunakannya untuk mengonversi bidang tanggal (setelah menghapus trailing <br>, jika ada) menjadi detik-sejak-zaman dan membandingkan langsung ke tanggal cutoff dalam format yang sama, misalnya dalam bash

testsecs=$(date +%s --date="2013/12/03")
while IFS= read -r line; do
  read -r x d <<< "$line" 
  if (( $(date +%s --date="${d%<br>}") < $testsecs )); then
    printf '%s\n' "$line"
  fi
done < buildsave.txt

[Perhatikan bahwa ini tidak melakukan penghapusan di tempat - Anda harus menyimpan hasilnya ke file sementara dan mengganti nama.]

Steeldriver
sumber
Anda Tuan menyelamatkan saya sakit kepala. Ini persis apa yang saya cari!
Jason G
yuck! Tanggal-tanggal tersebut mengurutkan leksikografis dan kronologis yang sama, tidak perlu mengubahnya menjadi integer dan menjalankan 5 perintah, buat satu file temp dan dua pipa per baris!
Stéphane Chazelas
9

Tanggal-tanggal itu mengurutkan leksikografis dan kronologis yang sama, jadi itu hanya masalah melakukan perbandingan leksikal:

awk '$2 < "2013/12/03"'
Stéphane Chazelas
sumber
2

Saya berasumsi <br>dalam pertanyaan Anda di akhir datekolom adalah sesuatu yang tidak diinginkan. Bagaimanapun, itu dapat dihapus dengan mudah jika ada. Namun, datang ke bagian utama Anda dapat mencapai apa yang Anda coba lakukan dengan menggunakan,

sort -k 2n filename.txt

Sekarang, perintah di atas akan memberikan output dengan cara diurutkan. Sekarang, perintah di bawah ini akan memberikan apa yang Anda cari.

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Penjelasan

Perintah sortir pada dasarnya mengurutkan file berdasarkan kolom kedua yang merupakan tanggal. Jadi saya memodifikasi file input Anda untuk menguji perintah jika berfungsi karena file input memiliki semua data yang diurutkan secara default. Setelah itu, awkperintah mencetak semua baris sampai kita menemukan kecocokan tertentu.

Pengujian

cat filename.txt

647919 2014/01/01
647946 2012/11/30
647955 2011/01/04
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04

Sekarang, sort -k 2n filename.txtkeluarannya adalah,

647955 2011/01/04
647946 2012/11/30
648266 2013/12/03
648267 2013/12/03
648674 2013/12/04
647919 2014/01/01

Sekarang kami puas bahwa file tersebut diurutkan pada kolom kedua. Sekarang, untuk memilih nilai-nilai UPTO pada tanggal tertentu,

sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Dalam contoh di atas, saya mendapatkan semua nilai upto 2013/12/03. Outputnya adalah,

647955 2011/01/04
647946 2012/11/30

Tidak, <br>ini bagian dari file saya

Jika demikian, kita dapat mengubah sedikit perintah seperti di bawah ini.

awk '{print $1, substr($2, 1, length($2)-4)}' filename.txt | 
sort -k 2n filename.txt | awk '/2013\/12\/03/ {exit} {print}' 

Jadi saya hanya menghapus semua <br>tag dari kolom kedua dan kemudian mengirim perintah yang disebutkan di atas.

Referensi

https://unix.stackexchange.com/a/11323/47538

https://unix.stackexchange.com/a/83069/47538

Ramesh
sumber
Terima kasih atas masukannya. ini memang bekerja sangat baik, kondisi untuk keluar tidak selalu berfungsi ketika tanggal tertentu tidak ada dalam file.
Jason G
tidak, tag br tampaknya ditambahkan hanya untuk membuat hal itu dapat dibaca. Mereka tidak dapat dilihat dalam revisi pertama
Braiam
-1

Solusi cepat dan kotor untuk satu tanggal yang Anda berikan, hapus saja semua baris dengan sed, yang cocok dengan tanggal setelah tanggal ini:

sed -i "" "#[0-9]* 2013/12/0[4-9]#d" testfile.txt
sed -i "" "#[0-9]* 2013/12/[123][0-9]#d" testfile.txt
sed -i "" "#[0-9]* 2014/[0-9][0-9]/[0-3][0-9]#d" testfile.txt

-I "" sedang menggantikan langsung di dalam file dan tidak membuat cadangan, tetapi Anda juga bisa mem-pipe testfile melalui semua 3 perintah sed tanpa -i "".

Bergantung pada sistem Anda (linux atau mac), Anda dapat menonaktifkan "" setelah -i dan kadang-kadang Anda membutuhkan parameter -e untuk ekspresi reguler. Harus mencoba apa yang cocok untuk Anda.

Pertanyaan terkait dengan info lebih lanjut tentang sed: /programming/5410757/

toppy
sumber
#adalah perintah komentarsed , sehingga mereka tidak akan melakukan apa pun. Gunakan sed '\#patter#d'jika Anda ingin pembatas RE yang berbeda dari /. Bagian [0-9]*itu berlebihan tanpa ^jangkar. -ehanya diperlukan ketika Anda ingin memberikan beberapa ekspresi. linux adalah kernel, mac adalah merek komputer, tidak ada yang ada hubungannya dengan sed. Perbedaannya adalah antara GNU seddan FreeBSD sed(yang OS / X (seperti yang ditemukan pada beberapa mac) diwarisi).
Stéphane Chazelas