2016-01-13 14 views
5

Tôi có df này:nhân vật Tính của một phần của một chuỗi

dput(df) 
structure(list(URLs = c("http://bursesvp.ro//portal/user/_/Banco_Votorantim_Cartoes/0-7f2f5cb67f1-22918b.html", 
"http://46.165.216.78/.CartoesVotorantim/Usuarios/Cadastro/BV6102891782/", 
"http://www.chalcedonyhotel.com/images/promoc/premiado.tam.fidelidade/", 
"http://bmbt.ro/portal/a3/_Votorantim_/VotorantimCartoes2016/0-7f2f5cb67f1-22928b.html", 
"http://voeazul.nl/azul/")), .Names = "URLs", row.names = c(NA, 
-5L), class = "data.frame") 

Nó mô tả các URL khác nhau và tôi đang cố gắng để đếm số ký tự của tên chủ, cho dù đó là một tên thực tế (http://hostname.com/....) Hoặc IP (http://000.000.000.000/...). Tuy nhiên, nếu nó là một tên thực tế, sau đó tôi chỉ muốn nchar giữa www. và .com. Nếu đó là một IP thì tất cả các số của nó và "ở giữa" dấu chấm.

kết quả mong đợi cho dữ liệu mẫu trên:

exp_outcome 
1   8 
2   13 
3   15 
4   4 
5   7 

tôi cố gắng làm điều gì đó với strsplit nhưng không thể có được bất cứ nơi nào.

Trả lời

7

Một cách trực tiếp có thể nhiều hơn với một regex khác nhau:

nchar(sub("^http://(www\\.)?(([a-z]+)|([0-9.]+))(\\.[a-z]+)?/+.+$", "\\2", x$df)) 
#[1] 8 13 15 4 7 

giải thích:

  • ^http://: tìm kiếm "http: //" sau khi bắt đầu của chuỗi
  • (www\\.)?: tìm kiếm "www.", Không hoặc một lần (vì vậy đây là tùy chọn)
  • (([a-z]+)|([0-9.]+)): mẫu sẽ được chụp: chữ thường viết một hoặc nhiều thời gian hoặc chữ số và các điểm
  • (\\.[a-z]+)?: tìm kiếm "." theo sau là một hoặc nhiều chữ thường, zero hoặc một lần (như vậy một lần nữa bắt buộc)
  • /+.+$: tìm kiếm "/" theo sau bởi bất cứ điều gì, một hoặc nhiều lần cho đến khi kết thúc chuỗi

NB:

sub("^http://(www\\.)?(([a-z]+)|([0-9.]+))(\\.[a-z]+)?/+.+$", "\\2", x$df) 
# [1] "bursesvp"  "46.165.216.78" "chalcedonyhotel" "bmbt"   "voeazul" 
+0

Điều này thật tuyệt vời và tôi thích giải pháp của riêng mình - nhưng tôi phải hỏi: tại sao viết '[/] {2}' thay vì '/ {2}' hoặc thậm chí '//' và tại sao viết 'w {3}' thay vì 'www'? Nó dài hơn và ít dễ đọc hơn. Ngoài ra, thay vì '(www) *' bạn nên sử dụng '(www)? 'Bởi vì chúng tôi muốn" số không hoặc một ", không phải" số không hoặc nhiều hơn "(và tương tự sau). Và một điều cuối cùng: tên miền có thể chứa nhiều hơn chỉ là chữ cái, chúng cũng có thể chứa chữ số và dấu gạch ngang và nhiều thứ khác. Vì vậy, một lớp nhân vật sẽ không cắt nó, bạn có thể phải chấp nhận bất cứ điều gì ngoại trừ '.' và'/'ở đây. –

+0

@KonradRudolph cảm ơn, [/] đó là tránh phải trốn thoát/và [//] sẽ không hoạt động. w {3} nó chỉ vì tôi không muốn lặp lại www (lựa chọn cá nhân ...). Cảm ơn vì nhận xét về "?", Nó thực sự sẽ phù hợp hơn. Tôi không quen? ngoài những cách nhìn khác. – Cath

+0

Trên thực tế, [Wikipedia nói] (https://en.wikipedia.org/wiki/Domain_name) chỉ có các ký tự và số được phép trong tên miền và dấu gạch ngang khi được bao quanh bởi tên cũ (vì vậy điều này đơn giản hóa một sửa chữa cho mối quan tâm của tôi đã lưu ý ở trên). Và không cần phải trốn thoát '/'. Chỉ '\\' cần phải được thoát. –

5

Dưới đây là làm thế nào để làm điều đó (giả sử bạn data.frame được gọi x):

domains = sub('^(http://)([^/]+)(.*)$', '\\2', x$df) 
# This will fail for IP addresses … 
hostname = sub('^(www\\.)?([^.]+)(\\..+)?$', '\\2', domains) 
# … which we treat separately here: 
is_ip = grepl('^(\\d{1,3}\\.){3}\\d{1,3}$', domains) 
hostname[is_ip] = domains[is_ip] 

exp_outcome$domain_length = nchar(hostname) 

Trên một mặt lưu ý, tôi chuyển data.frame ban đầu của bạn để chuỗi ký tự - nó chỉ đơn giản là làm cho không có ý nghĩa để sử dụng một factor cho URL.

0

sau 5 tháng đối phó với URL nói chung, tôi thấy các gói sau đó làm cho cuộc sống dễ dàng hơn một chút (Regex được cung cấp bởi câu trả lời khác làm công việc tuyệt vời bằng cách),

library(urltools) 
library(iptools) 

df$Hostname <- domain(df$URLs) 
#However, TLDs and 'www' need to go so I used suffix_extract()$domain from `iptools` 
df$Hostname <- ifelse(is.na(suffix_extract(df$Hostname)$domain), df$Hostname, 
              suffix_extract(df$Hostname)$domain) 

#which gives: 
# URLs               Hostname 
#1 http://bursesvp.ro//portal/user/_/...       bursesvp 
#2 http://46.165.216.78/.CartoesVotorantim/Usuarios/...   46.165.216.78 
#3 http://www.chalcedonyhotel.com/images/promoc/     chalcedonyhotel 
#4 http://bmbt.ro/portal/a3/_Votorantim_/...      bmbt 
#5 http://voeazul.nl/azul/          voeazul 

#then simply, 

nchar(df$Hostname) 
#[1] 8 13 15 4 7 
Các vấn đề liên quan