Not sure about most efficient, but here's one way to do it using c#.
A more efficient way would be to first parse the entire text into objects, and then only search the already parsed text.
usingSystem;usingSystem.Collections.Generic;usingSystem.Text.RegularExpressions;publicclassProgram{publicstaticvoidMain(){vars=@"/+1-541-754-3010 156 Alphand_St. <J Steeve>
133, Green, Rd. <E Kustur> NY-56423 ;+1-541-914-3010!
<Anastasia> +48-421-674-8974 Via Quirinal Roma
<Too many> some text +48-421-674-8974 ";Console.WriteLine(phone(s,"1-541-754-3010"));// return J SteeveConsole.WriteLine(phone(s,"1-541-914-3010"));// return E KusturConsole.WriteLine(phone(s,"48-421-674-8974"));// return Error => Too many people: nbConsole.WriteLine(phone(s,"48-421-674-1234"));// return Error => Not found: nb}staticstringphone(stringphoneBook,stringphoneNumber){varentries=newDictionary<string,PhoneBookEntry>();varlines=phoneBook.Split('\n');foreach(varlineinlines){if(PhoneBookEntry.TryParse(line,outPhoneBookEntryentry)&&entry.Phone==phoneNumber){if(entries.ContainsKey(entry.Phone)){return"Error => Too many people: nb";}entries[entry.Phone]=entry;}}if(entries.TryGetValue(phoneNumber,outPhoneBookEntryresult)){returnresult.ToString();}return"Error => Not found: nb";}privateclassPhoneBookEntry{privatestaticRegex_phoneRe=newRegex(@"\+(\d{1,2}-\d{3}-\d{3}-\d{4})");privatestaticRegex_nameRe=newRegex(@"<([^>]+)>");privatestaticRegex_specialCharsRe=newRegex(@"[/!;]");privatePhoneBookEntry(stringphone,stringaddress,stringname){Phone=phone;Address=address;Name=name;}publicstringPhone{get;}publicstringAddress{get;}publicstringName{get;}publicstaticboolTryParse(stringrawData,outPhoneBookEntryresult){result=null;varphoneMatch=_phoneRe.Match(rawData);if(phoneMatch.Success){varnameMatch=_nameRe.Match(rawData);if(nameMatch.Success){varphone=phoneMatch.Groups[1].Value;varname=nameMatch.Groups[1].Value;varaddress=_specialCharsRe.Replace(_nameRe.Replace(_phoneRe.Replace(rawData,""),""),"").Trim();result=newPhoneBookEntry(phone,address,name);returntrue;}}returnfalse;}publicoverridestringToString(){return$"Phone => {Phone}, Name => {Name}, Address => {Address}";}}}
Not sure about most efficient, but here's one way to do it using c#.
A more efficient way would be to first parse the entire text into objects, and then only search the already parsed text.
try it online