Ответ Джереми Рутена близок, но не удастся, если после имени хоста появится @. Я бы предложил:
(все, что не является '@') // необязательно
(?: [^ @: /] * @)
Двоеточие и косая черта препятствуют сопоставлению за доменом, если после домена появляется @. Обратите внимание на не захватывание паренов.
(все, что не является '/' до первого '/' ЕСЛИ оно там)
// это группа хостов, которую я хочу
([^: /] +)
Обратите внимание на захват парней.
(все остальное, что тянется) // необязательно
Поскольку парены заключают в себе имя хоста и только имя хоста, нет необходимости продолжать сопоставление.
Итак, сложив все вместе, вы получите:
/ ^ (?:? FTP | HTTPS): // (?: [^ @: /] * @) ([^: /] +) /
(Обратите внимание, что первые две родственные группировки не захватывают - надеюсь, ваша библиотека регулярных выражений это поддерживает.)