xóa các dòng mới hơn ngày đã cho trong một tệp


8

Tôi bế tắc về cách tôi có thể xóa các dòng mới hơn ngày đã cho. Đây là một đoạn nội dung của một tập tin.

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

Tôi muốn xóa các dòng mới hơn 2013/12/03 chỉ để lại

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

Làm thế nào điều này có thể được thực hiện thông qua bash?

Câu trả lời:


4

Nếu hệ thống của bạn bao gồm phiên bản GNU của datelệnh, bạn có thể sử dụng lệnh đó để chuyển đổi trường ngày (sau khi tước dấu <br>, nếu có) thành giây-kể từ epoch và so sánh trực tiếp với ngày cắt ở cùng định dạng, ví dụ như trong 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

[Lưu ý rằng việc này không thực hiện xóa tại chỗ - bạn cần lưu kết quả vào một tệp tạm thời và đổi tên.]


Bạn đã cứu tôi đau đầu. Điều này thật đúng với gì mà tôi đã tìm kiếm!
Jason G

kinh quá! Những ngày đó sắp xếp theo thứ tự từ vựng và thời gian giống nhau, không cần chuyển đổi chúng thành số nguyên và chạy 5 lệnh, tạo một tệp tạm thời và hai ống trên mỗi dòng!
Stéphane Chazelas

9

Những ngày đó sắp xếp theo thứ tự từ vựng và thời gian giống nhau, vì vậy đó chỉ là vấn đề thực hiện so sánh từ vựng:

awk '$2 < "2013/12/03"'

2

Tôi cho rằng <br>trong câu hỏi của bạn ở cuối datecột là điều không mong muốn. Trong mọi trường hợp, nó có thể được gỡ bỏ dễ dàng nếu nó có mặt. Tuy nhiên, đến phần chính bạn có thể đạt được những gì bạn đang cố gắng sử dụng,

sort -k 2n filename.txt

Bây giờ, lệnh trên sẽ cung cấp đầu ra theo cách được sắp xếp. Bây giờ, lệnh dưới đây sẽ cung cấp cho những gì bạn tìm kiếm.

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

Giải trình

Lệnh sort về cơ bản sắp xếp tệp dựa trên cột thứ hai là ngày. Vì vậy, tôi đã sửa đổi tệp đầu vào của bạn để kiểm tra lệnh nếu nó hoạt động vì tệp đầu vào có tất cả dữ liệu được sắp xếp theo mặc định. Sau đó, awklệnh in tất cả các dòng cho đến khi chúng ta gặp một trận đấu cụ thể.

Kiểm tra

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

Bây giờ, sort -k 2n filename.txtđầu ra là,

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

Bây giờ chúng tôi hài lòng rằng tập tin được sắp xếp trên cột thứ hai. Bây giờ, để chọn giá trị UPTO một ngày cụ thể,

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

Trong ví dụ trên, tôi nhận được tất cả các giá trị tối đa 2013/12/03. Đầu ra là,

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

Không, <br>là một phần của tập tin của tôi

Nếu đây là trường hợp, chúng ta có thể điều chỉnh lệnh một chút như dưới đây.

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

Vì vậy, tôi chỉ loại bỏ tất cả các <br>thẻ từ cột thứ hai và sau đó đường ống lệnh đã đề cập ở trên.

Người giới thiệu

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

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


cảm ơn về thông tin bạn vừa nhập. điều này thực sự hoạt động rất tốt, tuy nhiên, điều kiện để thoát không phải lúc nào cũng hoạt động khi ngày cụ thể không tồn tại trong tệp.
Jason G

không, các thẻ br dường như được thêm vào chỉ để làm cho mọi thứ dễ đọc hơn. Chúng không thể được nhìn thấy trong phiên bản đầu tiên
Braiam

-1

Giải pháp nhanh và bẩn cho một ngày bạn đã cung cấp, chỉ cần xóa tất cả các dòng bằng sed, ngày đó khớp với ngày muộn hơn ngày này:

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 "" đang thay thế trực tiếp bên trong tệp và không tạo bản sao lưu, nhưng bạn cũng có thể chuyển testfile qua tất cả 3 lệnh sed mà không có -i "".

Tùy thuộc vào hệ thống của bạn (linux hoặc mac), bạn có thể sử dụng "" sau -i và đôi khi bạn cần tham số -e cho các biểu thức thông thường. Hãy thử những gì làm việc cho bạn.

Câu hỏi liên quan với thông tin thêm về sed: /programming/5410757/


#là lệnh bình luậnsed , vì vậy những người đó sẽ không làm gì cả. Sử dụng sed '\#patter#d'nếu bạn muốn một dấu phân cách RE khác hơn /. Phần [0-9]*là dư thừa mà không có ^neo. -echỉ cần thiết khi bạn muốn vượt qua một vài biểu thức. linux là kernel, mac là một thương hiệu máy tính, không có gì để làm sed. Sự khác biệt là giữa GNU sedvà FreeBSD sed(mà OS / X (như được tìm thấy trên một số máy Mac) được kế thừa).
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.