use strict; use warnings; use feature "say"; while (){ my @ips = m/\(([\d\.:]+)[\s<>]*([\d\.:]+)?[\s<>]*([\d\.:]+)?\)/; $_ and say "$. >$_<" for @ips; } __DATA__ email (209.85.208.68) (172.217.194.27 < 209.85.208.68) (172.217.194.27 < 2001:4860:4860:0:0:0:0:8888) (2001:4860:4860:0:0:0:0:8888) (2001:4860:4860:0:0:0:0:8888 < 2001:4860:4860::8844) (2001:4860:4860:0:0:0:0:8888 < 172.217.194.27) (2001:4860:4860:0:0:0:0:9999 < 172.217.194.29 Not terminated by close paren Sometimes, it appears in this way too. It may have IPV6 as well. (172.217.194.27 < 172.217.194.27 < 209.85.208.68) Anyway, I stared with below. It won't fulfill. It can catch ipv #### 2 >209.85.208.68< 3 >172.217.194.27< 3 >209.85.208.68< 4 >172.217.194.27< 4 >2001:4860:4860:0:0:0:0:8888< 5 >2001:4860:4860:0:0:0:0:8888< 6 >2001:4860:4860:0:0:0:0:8888< 6 >2001:4860:4860::8844< 7 >2001:4860:4860:0:0:0:0:8888< 7 >172.217.194.27< 10 >172.217.194.27< 10 >172.217.194.27< 10 >209.85.208.68<