Sua expressão regular é
target="_blank">([[:graph:]]*)\.(jpg|png|gif|webm)
Corresponde ao texto literal target="_blank"> , seguido por qualquer número de caracteres que não sejam espaços em branco, com uma das quatro sequências .jpg , .png , .gif ou .webm no final. Por exemplo, o comando grep mostraria as partes em negrito das seguintes linhas:
<a … target="_blank">something.jpg</a>
<a … target="_blank">a.gifted.child.txt</a>
<a … target="_blank">something else.jpg</a>
<a … target="_blank">something.jpg</a>+more.jpg
E se você usar [[:print:]] em vez de [[:graph:]] , isso corresponderia a algo como
<a … target="_blank">something.jpg</a> wibble wobble <a … target="_blank">something else.jpg</a>
Tudo entre o primeiro bit target … correspondente e o último ramal correspondente na linha é uma correspondência.
O que você precisa é excluir os caracteres de marcação HTML da correspondência.
target="_blank">[^<>]*\.(jpg|png|gif|webm)</a>
Com o GNU grep, você pode usar a opção -P para obter construções de expressões regulares Perl e, em particular, asserções de largura zero que permitem especificar que algo é precedido ou seguido por algum texto constante sem incluir esse texto no texto porção correspondida.
grep -o -P '(?<target="_blank">)[^<>]*\.(jpg|png|gif|webm)(?=</a>)'
Isso ainda pode falhar se houver espaço em branco inesperado (como uma nova linha entre a tag <a> e o fechamento </a> ou). Você faria melhor usar um analisador HTML adequado .
Por exemplo, em Python com BeautifulSoup (não testado):
import re, sys, BeautifulSoup
soup = BeautifulSoup(sys.stdin)
for hit in soup.find_all('a', target='_blank'):
if re.match(r'.*\.(jpg|png|gif|webm)\Z', hit.string):
print(hit.string)
Código semelhante pode ser escrito com HTML::Parser em Perl, Nokogiri em Ruby, etc.