Обычно человечество решает такую проблему построением индексов.
В некоторых случаях возможно обойтись простой сортировкой - по отсортированному файлу можно легко искать методом половинного деления и лопатить при этом не весь файл, а только его малую часть.
Если же файл не отсортирован, и индексов никаких нет, то иначе чем полным перебором эта проблема не решается в принципе. И пох, будет это делать виндовый find или юниховый grep или ты сам на php. Алгоритмически это время одного порядка.
И да, весь файл загружать в память не нужно, т.е. лучше в цикле fgets() чем один раз file(). Оно само прочитает сколько надо в кеш и будет тебе построчно выдавать, каждый раз дисковую систему дергать не будет. Много памяти - большой кеш, мало - маленький, но это все на уровне операционной системы решается, а значит везде работает. По-любому не вылетит от нехватки памяти на большом файле и при этом оптимально сократит обращения к диску.