O * s após (\$) e (\=) significa, como sempre, zero ou mais.
O .*\n? significa zero ou mais de qualquer caractere (opcionalmente) (devido ao ? , que significa zero ou um) seguido por \n .
Isso significa que .*(\$)*(\=)*(\<).*\n? corresponderá a qualquer linha com (\<) , independentemente de ela ser precedida por um escape $ e / ou = ou não.
Em inglês, o regexp é lido como "zero ou mais caracteres, seguido opcionalmente por $ , então talvez um = , depois um < (não opcional) e, em seguida, zero ou mais caracteres , opcionalmente seguido por uma nova linha. "
Em outras palavras, o regexp inteiro, ignorando as capturas, é equivalente a apenas < . É a única coisa no regexp que não é opcional.
BTW, use + em vez de * se você quer dizer um ou mais.
Você pode querer tentar algo mais como:
grep -P '\$var\s*=\s*['"].*<[^>]+>'
Corresponde a $var seguido por zero ou mais caracteres de espaços em branco, em seguida, um = , em seguida, zero ou mais espaços em branco novamente, seguidos por ' ou " , depois zero-or- mais de qualquer caractere seguido por um < , em seguida, qualquer caractere exceto a > , seguido por um > .
por exemplo. $var='....<h1>' corresponderia.
Note que isso não vai pegar $var='htmlcode' , onde há uma nova linha entre o 'var =' e qualquer html.