2013-02-25 39 views
16

Tôi có một tệp dữ liệu chứa một cột văn bản chứa tên tệp. Tôi muốn trả lại tên tệp mà không có đường dẫn hoặc phần mở rộng của tệp. Thông thường, tên tệp của tôi đã được đánh số, nhưng chúng không nhất thiết phải như vậy. Ví dụ:Tên tệp trả về Regex, xóa đường dẫn và phần mở rộng tệp

df<-data.frame(data=c("a","b"),fileNames=c("C:/a/bb/ccc/NAME1.ext","C:/a/bb/ccc/d D2/name2.ext")) 

Tôi muốn quay trở lại tương đương với

df<-data.frame(data=c("a","b"),fileNames=c("NAME","name")) 

nhưng tôi không thể tìm ra các biểu thức chính quy trơn để làm điều này với gsub. Ví dụ, tôi có thể thoát khỏi phần mở rộng với (được cung cấp tên tập tin kết thúc bằng một số):

gsub('([0-9]).ext','',df[,"fileNames"]) 

Mặc dù tôi đã cố gắng mô hình khác nhau (bằng cách đọc các tập tin regex giúp đỡ và giải pháp tương tự trên trang web này), Tôi không thể có được một regex để trả lại văn bản giữa "/" cuối cùng và "." Đầu tiên. Bất kỳ suy nghĩ hoặc chuyển tiếp đến các câu hỏi tương tự được nhiều đánh giá cao!

Điều tốt nhất tôi đã nhận được là:

gsub('*[[:graph:]_]/|*[[:graph:]_].ext','',df[,"fileNames"]) 

Nhưng 1 này) không thoát khỏi tất cả các nhân vật con đường dẫn và 2) là phụ thuộc vào một phần mở rộng tập tin cụ thể.

Trả lời

33

Có lẽ điều này sẽ giúp bạn gần gũi hơn với giải pháp của bạn:

library(tools) 
basename(file_path_sans_ext(df$fileNames)) 
# [1] "NAME1" "name2" 

Chức năng file_path_sans_ext là từ "công cụ" gói (mà tôi tin thường đi kèm với R), và điều đó sẽ trích xuất các con đường lên đến (nhưng không bao gồm) phần mở rộng. Chức năng basename sau đó sẽ loại bỏ thông tin đường dẫn của bạn.

Hoặc, để mất từ ​​file_path_sans_ext và sửa đổi nó một chút, bạn có thể thử:

sub("(.*\\/)([^.]+)(\\.[[:alnum:]]+$)", "\\2", df$fileNames) 
# [1] "NAME1" "name2" 

Ở đây, tôi đã "bắt" tất cả ba phần của các biến "tên tập tin", vì vậy nếu bạn muốn chỉ đường dẫn tệp, bạn sẽ thay đổi "\\2" thành "\\1" và nếu bạn chỉ muốn tiện ích mở rộng tệp, bạn sẽ thay đổi thành "\\3".

+0

Cách tiếp cận thú vị. Đối với tôi, cách tiếp cận này rõ ràng hơn so với regex, điều này hiện đang gây nhầm lẫn cho tôi. Tôi sẽ thử. – Docuemada

+0

Điều này hoạt động tốt, cảm ơn bạn. Nó có ý nghĩa hơn với tôi, nhưng đó có lẽ là vì tôi cần luyện tập nhiều hơn với regex! – Docuemada

+0

@Docuemada, không sao cả. Như được hiển thị, 'file_path_sans_ext' là một biểu thức chính quy cơ bản, vì tôi nghi ngờ' basename' là (nhưng chưa được kiểm tra để xác minh). – A5C1D2H2I1M1N2O1R2T1

9

Trước hết, để loại bỏ "đường dẫn hàng đầu", bạn có thể sử dụng basename. Để loại bỏ các phần mở rộng, bạn có thể sử dụng sub tương tự như mô tả của bạn trong câu hỏi của bạn:

filenames <- sub("\\.[[:alnum:]]+$", "", basename(as.character(df$fileNames))) 

Lưu ý rằng bạn nên sử dụng sub thay vì gsub đây, bởi vì phần mở rộng tập tin chỉ có thể xảy ra một lần cho mỗi tên tập tin. Ngoài ra, bạn nên sử dụng \\. khớp với một dấu chấm thay vì . khớp với bất kỳ biểu tượng nào. Cuối cùng, bạn nên thêm $ vào mẫu để đảm bảo rằng bạn đang xóa phần mở rộng chỉ khi nó ở cuối tên tệp.

Edit: chức năng file_path_sans_ext đề xuất trong giải pháp Ananda Mahto của công trình thông qua sub("([^.]+)\\.[[:alnum:]]+$", "\\1", x), ví dụ thay vì loại bỏ phần mở rộng như trên, phần phi mở rộng của tên tập tin được giữ lại. Tôi không thể thấy bất kỳ ưu điểm hoặc nhược điểm cụ thể nào của cả hai phương pháp trong trường hợp OP.

+1

Bạn có thể cần sử dụng 'as.character' quanh' df $ fileNames' nếu nó đã được đọc dưới dạng một yếu tố, như trong dữ liệu ví dụ được cung cấp. – A5C1D2H2I1M1N2O1R2T1

+0

@Ananda Đã chỉnh sửa, cảm ơn. – QkuCeHBH

+0

Cảm ơn bạn và cảm ơn bạn đã giải thích các ký tự regexp. Điều này hoạt động tốt. Trong ví dụ này, tôi đã sử dụng ... as.character (df $ fileNames). – Docuemada

Các vấn đề liên quan