gì về sử dụng awk
? Bạn có thể nhận được sự xuất hiện đầu tiên thực sự đơn giản:
[[email protected] ~]$ cat data1
./501.res/1.bin
./503.res/1.bin
./503.res/2.bin
./504.res/1.bin
[[email protected] ~]$ awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' data1
./501.res/1.bin
./503.res/1.bin
./504.res/1.bin
[[email protected] ~]$
Để có được sự xuất hiện cuối cùng bạn có thể đường ống thông qua một vài loại:
[[email protected] ~]$ sort -r data1 | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort
./501.res/1.bin
./503.res/2.bin
./504.res/1.bin
[[email protected] ~]$
Cho rằng bạn đang sử dụng "tìm" và "grep" , bạn có thể có thể làm điều này:
find . -name \*.bin -type f -print | sort -r | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort
Cách thức hoạt động?
Lệnh find
có nhiều tùy chọn hữu ích, bao gồm khả năng chọn tệp của bạn theo glob, chọn loại tệp, v.v ... đầu ra của nó mà bạn đã biết và trở thành đầu vào là sort -r
.
Đầu tiên, chúng tôi sắp xếp dữ liệu đầu vào của chúng tôi ngược lại (sort -r
). Điều này đảm bảo rằng trong bất kỳ thư mục nào, tệp được đánh số cao nhất sẽ hiển thị trước tiên. Kết quả đó được cho ăn vào vụng về. FS là bộ tách trường, làm cho $2
thành những thứ như "/ 501", "/ 502", v.v. Các tập lệnh Awk có các phần ở dạng condition {action}
được đánh giá cho từng dòng đầu vào. Nếu một điều kiện bị thiếu, hành động sẽ chạy trên mọi dòng. Nếu "1" là điều kiện và không có hành động, nó sẽ in ra dòng. Vì vậy, kịch bản này được chia ra như sau:
a[$2] {next}
- Nếu mảng a
với chỉ số dưới $ 2 (tức là "/ 501") tồn tại, chỉ cần nhảy tới dòng tiếp theo. Nếu không ...
{a[$2]=1}
- đặt mảng thành chỉ số $ 2 đến 1, để trong tương lai điều kiện đầu tiên sẽ đánh giá là đúng, thì ...
1
- in dòng.
Đầu ra của tập lệnh awk này sẽ là dữ liệu bạn muốn, nhưng theo thứ tự ngược lại. Cuối cùng sort
đặt mọi thứ trở lại theo thứ tự bạn mong đợi.
Bây giờ ... đó là rất nhiều ống, và sắp xếp có thể là một chút tài nguyên đói khi bạn yêu cầu nó để đối phó với hàng triệu dòng đầu vào cùng một lúc. Giải pháp này sẽ hoàn toàn đủ cho số lượng tệp nhỏ, nhưng nếu bạn đang xử lý số lượng lớn dữ liệu đầu vào, hãy cho chúng tôi biết và tôi có thể đưa ra giải pháp tất cả trong một (sẽ mất hơn 60 giây) viết).
CẬP NHẬT
lời khuyên khôn
mỗi Dennis', kịch bản awk tôi bao gồm ở trên có thể được cải thiện bằng cách thay đổi nó từ
BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1
để
BEGIN{FS="."} $2 in a {next} {a[$2]} 1
Trong khi điều này có chức năng giống hệt nhau , lợi thế là bạn chỉ cần định nghĩa các thành viên mảng thay vì gán các giá trị cho chúng, điều này có thể tiết kiệm bộ nhớ hoặc cpu de đang chờ bạn triển khai awk. Ở mức nào, nó sạch hơn.
Tốt hơn là kiểm tra sự tồn tại của một phần tử trong một mảng bằng cách sử dụng '$ 2 trong một {next}'. Làm theo cách đó không tạo ra các phần tử mảng mới chỉ đơn giản bằng cách tham chiếu đến chúng. Đây là những gì tôi muốn nói ngày hôm kia khi chúng tôi thảo luận về điều này. Bằng cách này, nếu bạn sử dụng 'in' theo cách đó, bạn có thể làm' {a [$ 2]} 'thay vì' {a [$ 2] = 1} ', nhưng sẽ hoạt động. –
@DennisWilliamson, AH, bây giờ tôi hiểu những gì bạn đã nhận được vào ngày khác. Cảm ơn rất nhiều cho con trỏ. :) – ghoti