Liệt kê với `ls` và biểu thức chính quy


14

Làm cách nào tôi có thể liệt kê các tệp có tên tệp kết thúc bằng ký tự cuối cùng và có .txtphần mở rộng?

Tôi đã cố gắng ls *+([[:digit:]]).txtnhưng điều này là đúng đối với abc12.txtabc2.txt.

Nhưng tôi chỉ cần có được abc2.txt. Làm thế nào tôi có thể làm điều đó?

Có bất kỳ hình thức sắp xếp :digit:nào sẽ làm điều này?


2
Cần lưu ý rằng mẫu chỉ có giá trị với tính năng mở rộng toàn cầu : shopt -s extglob.
donothings thành công

Câu trả lời:


19

Làm thế nào về:

ls *[!0-9][0-9].txt

!đầu nhóm bổ sung cho ý nghĩa của nó.

Như đã lưu ý trong các nhận xét, đây là cách làm của bash, hãy thử, ví dụ:

printf "%s\n" *[!0-9][0-9].txt

2
Lưu ý rằng bash (tức là ls) không hỗ trợ các biểu thức thông thường ở đây. Đây là các biểu thức tên tệp (Globbing) . Bạn có thể thấy sự khác biệt đã có trong ví dụ của bạn: ở đây, *là một ký tự đại diện, không có trong các biểu thức thông thường, nơi bạn sẽ sử dụng .*để đạt được điều tương tự. Biểu thức thông thường mạnh hơn rất nhiều so với Globing.
Christopher K.

2

Câu hỏi yêu cầu biểu thức chính quy. Bash, và do đó ls, không hỗ trợ các biểu thức thông thường ở đây. Những gì nó hỗ trợ là biểu thức tên tệp ( Globbing ), một dạng ký tự đại diện. Biểu thức thông thường mạnh hơn rất nhiều so với điều đó.

Nếu bạn thực sự muốn sử dụng các biểu thức thông thường, bạn có thể sử dụng find -regexnhư thế này:

find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt'

Tìm được đệ quy theo mặc định, nhưng lskhông. Để chỉ tìm các tệp trong thư mục hiện tại, bạn có thể tắt đệ quy với -maxdepth 1. Tìm kết quả khớp với tên tệp có đường dẫn, đó là lý do tại sao tên tệp bắt đầu bằng ./nếu bạn chạy find in .. Regex bắt đầu với \./để đối phó với điều đó. Lưu ý rằng trong regex, .là một ký tự đặc biệt khớp với bất kỳ ký tự nào, nhưng ở đây chúng tôi thực sự muốn có một dấu chấm, đó là lý do tại sao chúng tôi thoát khỏi nó bằng dấu gạch chéo ngược. Chúng tôi làm tương tự cho dấu chấm trong .txt, bởi vì biểu thức chính quy cũng sẽ khớp Atxt. Các lớp chữ số giống như đối với toàn cầu, chỉ là bạn cần ^thay vì !đảo ngược lớp ký tự.

Nếu bạn muốn có được đầu ra của ls, thì bạn có thể sử dụng -exec lsnhư thế này:

 find . -maxdepth 1 -regex '\./.*[^0-9][0-9]\.txt' -exec ls -lah {} \;

findhỗ trợ một vài hương vị regex khác nhau. Bạn có thể chỉ định một -regextype, ví dụ:

find . -maxdepth 1 -regextype egrep -regex '\./.*[^0-9][0-9]\.txt'

Đối với tôi, các loại có thể là: 'findutils-default', 'awk', 'egrep', 'ed', 'emacs', 'gnu-awk', 'grep', 'posix-awk', 'posix-basic' , 'posix-egrep', 'posix-Extended', 'posix-Minimal-basic', 'sed' Bạn có thể chạy find -regextype helpđể tìm hiểu những gì được hỗ trợ trên hệ thống của bạn.


0

Với các khối lượng mở rộng ksh (hoặc bash -O extglobhoặc zsh -o kshglob) mà bạn đang sử dụng, đó sẽ là:

ls -d -- ?(*[![:digit:]])[[:digit:]].txt

Hoặc là

ls -d -- !(*[[:digit:]])[[:digit:]].txt

Nếu bạn muốn phù hợp a1.txt 2.txt không a12.txtcũng không 12.txt.

Tuy nhiên, lưu ý rằng trong ksh và bash (trừ khi bạn đặt failglobtùy chọn để có hành vi tương tự như zsh), nếu mẫu đó không khớp với bất kỳ tệp nào, mẫu sẽ được chuyển theo nghĩa đen lsvà nếu tệp đó (được đặt tên lạ) xảy ra tồn tại, nó sẽ được liệt kê bởi lsmặc dù nó không khớp với mẫu đó.

Bao gồm .2.txt, thiết lập các dotglobtùy chọn trong bash, thêm (D)vòng loại glob trong zsh, hoặc thiết lập FIGNOREđể !(.|..)ksh93.

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.