Stroustrup publicou recentemente uma série de posts desmistificando mitos populares sobre C ++ . O quinto mito é: "C ++ é somente para programas grandes e complicados". Para desmascará-lo, ele escreveu um programa C ++ simples, baixando uma página da Web e extraindo links dela . Aqui está:
#include <string>
#include <set>
#include <iostream>
#include <sstream>
#include <regex>
#include <boost/asio.hpp>
using namespace std;
set<string> get_strings(istream& is, regex pat)
{
set<string> res;
smatch m;
for (string s; getline(is, s);) // read a line
if (regex_search(s, m, pat))
res.insert(m[0]); // save match in set
return res;
}
void connect_to_file(iostream& s, const string& server, const string& file)
// open a connection to server and open an attach file to s
// skip headers
{
if (!s)
throw runtime_error{ "can't connect\n" };
// Request to read the file from the server:
s << "GET " << "http://" + server + "/" + file << " HTTP/1.0\r\n";
s << "Host: " << server << "\r\n";
s << "Accept: */*\r\n";
s << "Connection: close\r\n\r\n";
// Check that the response is OK:
string http_version;
unsigned int status_code;
s >> http_version >> status_code;
string status_message;
getline(s, status_message);
if (!s || http_version.substr(0, 5) != "HTTP/")
throw runtime_error{ "Invalid response\n" };
if (status_code != 200)
throw runtime_error{ "Response returned with status code" };
// Discard the response headers, which are terminated by a blank line:
string header;
while (getline(s, header) && header != "\r")
;
}
int main()
{
try {
string server = "www.stroustrup.com";
boost::asio::ip::tcp::iostream s{ server, "http" }; // make a connection
connect_to_file(s, server, "C++.html"); // check and open file
regex pat{ R"((http://)?www([./#\+-]\w*)+)" }; // URL
for (auto x : get_strings(s, pat)) // look for URLs
cout << x << '\n';
}
catch (std::exception& e) {
std::cout << "Exception: " << e.what() << "\n";
return 1;
}
}
Vamos mostrar ao Stroustrup o que é um programa pequeno e legível .
- Baixar
http://www.stroustrup.com/C++.html
Listar todos os links:
http://www-h.eng.cam.ac.uk/help/tpl/languages/C++.html http://www.accu.org http://www.artima.co/cppsource http://www.boost.org ...
Você pode usar qualquer idioma, mas nenhuma biblioteca de terceiros é permitida.
Vencedora
A resposta C ++ ganhou por votos, mas depende de uma biblioteca de terceiros (o que não é permitido por regras) e, junto com outro concorrente próximo Bash , conta com um cliente HTTP invadido (que não funcionará com HTTPS, gzip, redireciona etc.). Então Wolfram é um vencedor claro. Outra solução que se aproxima em termos de tamanho e legibilidade é o PowerShell (com melhorias nos comentários), mas não recebeu muita atenção. Linguagens mainstream ( Python , C # ) também chegaram bem perto.
Content-Type: text/html; charset=UTF-8
... vou enviar um e-mail para ele.boost/asio
é usado lá em cima, que é uma biblioteca de terceiros. Quero dizer, como os idiomas que não incluem a busca de url / tcp como parte de sua biblioteca padrão competem?Respostas:
Volfrâmio
Parece trapaça completa
Então, basta adicionar algumas análises honestas no topo
fonte
C ++
A principal falha é a natureza incômoda do boost :: asio, tenho certeza que pode ser ainda mais curta com uma biblioteca melhor.
fonte
import urllib2
, o C3 ainda pode serusing System.Net
, o Haskel pode aindaimport Network.HTTP
, mas um codificador C ++ deve dar desculpas#include <boost/asio.hpp>
como se tivesse um crapton métrico de bibliotecas especializadas em C ++ (e C!) disponíveis para escolher é algo para se envergonhar só porque a comissão não se preocupou em forçar-feed você um específico ...System.Net
não é forçado, é apenas uma biblioteca de alta qualidade, seguindo todas as recomendações .NET incluídas no idioma. Existem implementações alternativas, mas ter suporte a HTTP na biblioteca padrão significa escrever aplicativos simples é simples, significa melhor interoperabilidade entre bibliotecas de terceiros, significa menos dependências, significa fácil implementação para fachadas etc. Imagine um mundo semstd::string
, imagine como todos usam sua própria biblioteca, imagine todas as dificuldades que acompanham.urllib2
é de terceiros. Está no stdlib como no C ++. no Python está sempre disponível, diferentemente do C ++. Se tivéssemos permissão para usar módulos de terceiros; Eu usaria ou em Python.<iostream>
urllib2
<boost/asio.hpp>
lxml
BeautifulSoup
Pure Bash no Linux / OS X (sem utilitários externos)
O software cliente HTTP é notoriamente inchado. Não queremos esse tipo de dependência. Em vez disso, podemos enviar os cabeçalhos apropriados para um fluxo TCP e ler o resultado. Não é necessário chamar utilitários arcaicos como grep ou sed para analisar o resultado.
Meh - Suponho que poderia ser mais legível ...
fonte
mapfile
:)mapfile
vem com o bash 4.x. A mesma coisa é totalmente possível com umwhile read
loop também.while read
vez demapfile
. Mais portátil e mais legível, eu acho.Python 2
Manco, mas funciona
fonte
l = re.findall('"((http)s?://.*?)"', u.urlopen(s).read())
urlopen()
). O que deve fazer com essa exceção, além de falhar e morrer? Se ele vai falhar e morrer de qualquer maneira, por que não deixar o Python lidar com a falha e a morte e deixar de fora o tratamento de exceção?urlopen
erros do que (digamos) pegá-los e ligarsys.exit("something's borked!")
. Se eles fizerem o último, eu tenho que pegarSystemExit
, o que nunca é divertido.C #
fonte
var html
e provavelmentevar match
cortar alguns caracteres.html
variáveis também, mas não é disso que estou procurando.var
quando isso não afeta a semântica do código?"Nenhum terceiro" é uma falácia
Eu acho que a suposição de "não de terceiros" é uma falácia. E é uma falácia específica que afeta os desenvolvedores de C ++, pois é muito difícil criar código reutilizável em C ++. Quando você estiver desenvolvendo alguma coisa, mesmo que seja um script pequeno, sempre usará qualquer parte do código reutilizável disponível.
O problema é que, em linguagens como Perl, Python, Ruby (para citar alguns), reutilizar o código de outra pessoa não é apenas fácil, mas é como a maioria das pessoas realmente escreve código na maioria das vezes.
O C ++, com seus requisitos ABI quase impossíveis de manter, torna esse trabalho muito mais difícil; você acaba com um projeto como o Boost, que é um repositório monstruoso de código e com pouca composição fora dele.
Um exemplo de CPAN
Apenas por diversão, aqui está um exemplo baseado em CPAN, com análise adequada do html, em vez de tentar usar o regex para analisar o html
fonte
Shell UNIX
Também encontra um
ftp://
link :)Outra maneira, sem depender da
://
sintaxe:fonte
lynx
é funcionalmente equivalente a uma biblioteca de terceiros nesse cenário.CSS 3
Esse código pode ser usado como um estilo de usuário para exibir apenas links absolutos em uma página em uma lista não formatada. Pode não funcionar corretamente se o seu navegador aplicar o tamanho mínimo da fonte.
Funciona corretamente com
http://www.stroustrup.com/C++.html
(note!important
onbackground
). Para trabalhar em outras páginas com mais estilos, ele deve ser estendido (redefinir mais propriedades, marcar propriedades como importantes etc.).Versão alternativa que inclui links relativos, exceto os links entre páginas que começam com hashes (infelizmente, depende de um link absoluto codificado):
fonte
Clojure
fonte
spit
,zipper
elazy-cat
... :-)Emacs Lisp
fonte
Scala
fonte
ftp://ftp.research.att.com/pub/c++std/WP/CD2
?PHP 5
fonte
'/"((http)s?://.*?)"/'
⇒'|"((http)s?://.*?)"|'
(atualmente um erro); removearray_unshift($m);
(atualmente um erro, você provavelmente quis dizerarray_shift
);print_r($m);
⇒print_r($m[1]);
(apenas produz os URLs).PowerShell
Pesquisa de texto para todos os URLs totalmente qualificados (incluindo JavaScript, CSS etc.):
Ou para obter links apenas em tags âncora (inclui URLs relativos):
Versões mais curtas dos comentários:
fonte
iwr
é um apelido paraInvoke-WebRequest
(PS3 +).(iwr "http://www.stroustrup.com/C++.html").Links.href
(ou(iwr "http://www.stroustrup.com/C++.html").Links.href-match":"
apenas absoluta da URI)D
fonte
| sort | uniq
ou em vez adicionarimport std.array
e alterar a linha.filter!("a")){ writeln(_.front[1]); }
para o seguinte:.filter!("a").map!(a => a.front[1]).array.sort.uniq){ writeln(_); }
. Observe, no entanto, que eu apenas tentei esse código e não provei que ele estivesse correto ou "idiomático". :)Node.js
fonte
require('http').get
funciona. Se isso acontecer, podemos abandonar a instrução var e encurtar outra linha.Rubi
fonte
%r{"(https?://[^"]+)"}
. Além disso, você pode usarNet::HTTP.get('www.stroustrup.com', '/C++.html')
para encurtar a solicitação (e mantê-la legível). Assim código inteira pode estar em uma linha (mantendo-legível):puts Net::HTTP.get("www.stroustrup.com", "/C++.html").scan(%r{"(https?://[^"]+)"})
. Execute-oruby -rnet/http
e você nem precisa derequire 'net/http'
linha.Haskell
Alguns problemas
"\w"
no Text.Regex.Posixfonte
result
especificado é explicitamente? Deve ser totalmente restringido pelo seu uso emunlines
.Network.HTTP
nemTextRegex.Posix
existem nem estão nobase
pacote. (Embora estejam na plataforma Haskell e, é claro, no Hackage, então ...)network
também nãobase
está presente, portanto, exceto para rolar suas próprias ligações de soquete, não há maneira prática de fazer isso apenasbase
.PHP
Tanto quanto posso dizer, a maioria das instalações PHP modernas vem com processamento DOM, então aqui está uma que realmente atravessa as âncoras dentro do HTML:
O loop interno pode ser reduzido para:
fonte
1
vez detrue
para ain_array
pesquisa estrita. Você também pode omitir os colchetes. Não tenho certeza absoluta, mas você pode também largar ohttp
e sair do://
(sem o esquema). .if ( ) {}
favor dein_array() and print $url.PHP_EOL
. Mas sim, você teria outra +1 (se pudesse) para melhor legibilidade :)@\DOMDocument
. Só tentei isso e posso confirmar que funciona.::loadHTMLFile()
estaticamente e adicionar@
apenas oculta esse artefato.Shell Unix
Embora eu tenha que admitir que isso não funciona se houver mais de um link em uma linha.
fonte
curl http://www.stroustrup.com/C++.html
salva alguns caracteres.wget
é GNU (como é o bash), você poderia argumentar que não é de terceiros. Mascurl
definitivamente é de terceiros.ftp://ftp.research.att.com/pub/c++std/WP/CD2
ehttps://www.youtube.com/watch?v=jDqQudbtuqo&feature=youtu.be
?Java
fonte
Scanner
poderá fazê-lo processar o padrão de expressão regular para links diretamente e iterar sobre osScanner
resultados.Groovy
fonte
SQL (SQL Anywhere 16)
Definir um procedimento armazenado para buscar a página da web
Produza o conjunto de resultados usando uma única consulta
Limitações: Isso produz até 256 links. Se existirem mais links, aumente os 256 para um valor apropriado.
fonte
CoffeeScript / NodeJS
fonte
Perl
fonte
use v5.10;
esay for $response->content
...say
são bastante úteis e, em minha opinião, mais claros aqui. (Além disso, houve sim uma série de melhorias completamente-não relacionados-se perl6ism para perl5 nos últimos 13 anos, que poderia ser a pena conferir.)say
provavelmente seja mais legível nesse caso, principalmente para aqueles menos familiarizados com o perl.R
... embora R seja escrito principalmente em C ... provavelmente algumas linhas de código C por trás dessas 2 linhas de código R.
fonte
Objetivo-C
fonte
Tcl
fonte
[
. Mas essa é uma escolha de estilo.Ir
PS esse código lê toda a fonte na memória, então considere usar
regexp.FindReaderIndex
para pesquisar no fluxo, para tornar o aplicativo à prova de balas.fonte
CJam
O CJam não possui regex, então tive que usar uma abordagem diferente nesta:
Primeiro converto tudo
'
para"
, depois divido sobre tudo"
, pego todas as strings alternativas e, finalmente, filtre essa lista por strings começando comhttp://
orhttps://
. Depois disso, basta imprimir cada sequência filtrada em uma nova linha.Experimente usando o interpretador Java como
onde file.cjam possui o conteúdo do código acima.
fonte
''/'"f/:+
por''/'"*'"/'"f/0f=
.'"f/0f=
existe? Isso deveria fazer alguma coisa (2%
por exemplo)?F #
Esse código pode ser muito mais curto, mas eu escreveria algo assim se esperasse ter que ler ou usar esse código novamente, para que ele tenha muitas anotações de tipo desnecessárias. Demonstra o uso de um padrão ativo MatchValue para habilitar a correspondência de padrões com o tipo CLR padrão Match
Editar Eu criei a função getLinks
fonte