Stroustrup ha publicado recientemente una serie de publicaciones que desacreditan mitos populares sobre C ++ . El quinto mito es: "C ++ es solo para programas grandes y complicados". Para desacreditarlo, escribió un sencillo programa en C ++ que descarga una página web y extrae enlaces de ella . Aquí 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 a mostrarle a Stroustrup qué es un programa pequeño y legible .
- Descargar
http://www.stroustrup.com/C++.html
Listar todos los enlaces:
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 ...
Puede usar cualquier idioma, pero no se permiten bibliotecas de terceros.
Ganador
La respuesta de C ++ ganada por votos, pero se basa en una biblioteca de terceros (que no está permitida por las reglas) y, junto con otro competidor cercano, Bash , se basa en un cliente HTTP pirateado (no funcionará con HTTPS, gzip, redirecciones, etc.). Entonces Wolfram es un claro ganador. Otra solución que se acerca en términos de tamaño y legibilidad es PowerShell (con la mejora de los comentarios), pero no ha recibido mucha atención. Los lenguajes convencionales ( Python , C # ) también se acercaron bastante.
Content-Type: text/html; charset=UTF-8
... Voy a enviarle un correo electrónico.boost/asio
se usa allí, que es una biblioteca de terceros. Quiero decir, ¿cómo competirán los idiomas que no incluyen la obtención de url / tcp como parte de su biblioteca estándar?Respuestas:
Wolfram
Esto se siente como una trampa completa
Así que solo agrega un análisis honesto en la parte superior
fuente
C ++
La principal deficiencia es la naturaleza incómoda de boost :: asio, estoy seguro de que puede ser aún más corto con una mejor biblioteca.
fuente
import urllib2
, C3 aún puede serusing System.Net
, Haskel aún puedeimport Network.HTTP
, pero un codificador de C ++ debe dar excusas#include <boost/asio.hpp>
como si tuviera un crapton métrico de bibliotecas especializadas de C ++ (y C). disponible para elegir es algo de lo que avergonzarse solo porque el comité no se molestó en alimentarlo a la fuerza con uno específico ...System.Net
no es forzado, es solo una biblioteca de alta calidad que sigue todas las recomendaciones de .NET incluidas con el lenguaje. Hay implementaciones alternativas, pero tener soporte HTTP en la biblioteca estándar significa que escribir aplicaciones simples es simple, significa una mejor interoperabilidad entre bibliotecas de terceros, significa menos dependencias, significa una fácil implementación para fachadas, etc. Imagine un mundo sinstd::string
, imagine cómo todos usan su propia biblioteca, imagina todas las dificultades que vienen con ella.urllib2
es un tercero. Está en stdlib como<iostream>
en C ++.urllib2
en Python siempre está disponible a diferencia<boost/asio.hpp>
de C ++. Si se nos permitiera usar módulos de terceros; Yo usaríalxml
oBeautifulSoup
en Python.Pure Bash en Linux / OS X (sin utilidades externas)
El software de cliente HTTP está notoriamente inflado. No queremos ese tipo de dependencias. En su lugar, podemos empujar los encabezados apropiados hacia abajo en una secuencia TCP y leer el resultado. No es necesario llamar a servicios arcaicos como grep o sed para analizar el resultado.
Meh: supongo que podría ser más legible ...
fuente
mapfile
:)mapfile
viene con bash 4.x. Lo mismo es totalmente factible con unwhile read
bucle también.while read
lugar demapfile
. Más portátil y más legible, creo.Python 2
Cojo, pero funciona
fuente
l = re.findall('"((http)s?://.*?)"', u.urlopen(s).read())
urlopen()
). ¿Qué debería hacer con tal excepción, aparte de estrellarse y morir? Si se va a estrellar y morir de todos modos, ¿por qué no dejar que Python se encargue de los accidentes y las muertes, y dejar de lado el manejo de excepciones?urlopen
errores que (digamos) los atrapen y llamensys.exit("something's borked!")
. Si hacen lo último, tengo que atraparloSystemExit
, lo cual nunca es divertido.C#
fuente
var html
, y probablementevar match
para afeitarse algunos caracteres.html
variable por completo también, pero no es lo que busco.var
cuando no afectará la semántica del código?"Ningún tercero" es una falacia
Creo que la suposición de "no terceros" es una falacia. Y es una falacia específica que afecta a los desarrolladores de C ++, ya que es muy difícil crear código reutilizable en C ++. Cuando desarrolle algo, incluso si se trata de un script pequeño, siempre utilizará las piezas de código reutilizables disponibles.
La cuestión es que, en lenguajes como Perl, Python, Ruby (por nombrar algunos), reutilizar el código de otra persona no solo es fácil, sino que es cómo la mayoría de las personas realmente escriben código la mayor parte del tiempo.
C ++, con sus requisitos ABI casi imposibles de mantener, hace que sea un trabajo mucho más difícil, terminas con un proyecto como Boost, que es un depósito monstruoso de código y muy poca compostura fuera de él.
Un ejemplo de CPAN
Solo por diversión, aquí va un ejemplo basado en CPAN, con el análisis adecuado del html, en lugar de tratar de usar regex para analizar html
fuente
Shell de UNIX
También encuentra un
ftp://
enlace :)Otra forma, sin depender de la
://
sintaxis:fuente
lynx
es funcionalmente equivalente a una biblioteca de terceros en este escenario.CSS 3
Este código puede usarse como un estilo de usuario para mostrar solo enlaces absolutos en una página en una lista sin formato. Es posible que no funcione correctamente si su navegador exige un tamaño de fuente mínimo.
Funciona correctamente con
http://www.stroustrup.com/C++.html
(nota!important
sobrebackground
). Para trabajar en otras páginas con más estilos, debe ampliarse (restablecer más propiedades, marcar propiedades como importantes, etc.).Versión alternativa que incluye enlaces relativos, excepto los enlaces intrapágina que comienzan con hashes (lamentablemente, se basa en un enlace absoluto codificado):
fuente
Clojure
fuente
spit
,zipper
ylazy-cat
... :-)Emacs Lisp
fuente
Scala
fuente
ftp://ftp.research.att.com/pub/c++std/WP/CD2
?PHP 5
fuente
'/"((http)s?://.*?)"/'
⇒'|"((http)s?://.*?)"|'
(actualmente un error); eliminararray_unshift($m);
(actualmente es un error, probablemente quisiste decirlo en suarray_shift
lugar);print_r($m);
⇒print_r($m[1]);
(solo genera las URL).Potencia Shell
Búsqueda de texto para todas las URL totalmente calificadas (incluidos JavaScript, CSS, etc.):
O para obtener enlaces solo en etiquetas de anclaje (incluye URL relativas):
Versiones más cortas de los comentarios:
fuente
iwr
es un alias paraInvoke-WebRequest
(PS3 +).(iwr "http://www.stroustrup.com/C++.html").Links.href
(o(iwr "http://www.stroustrup.com/C++.html").Links.href-match":"
solo para URIs absolutos)re
fuente
| sort | uniq
o en lugar añadirimport std.array
y cambiar la línea.filter!("a")){ writeln(_.front[1]); }
en esto:.filter!("a").map!(a => a.front[1]).array.sort.uniq){ writeln(_); }
. Sin embargo, tenga en cuenta que solo he probado este código y no he demostrado que sea correcto o "idiomático". :)Node.js
fuente
require('http').get
funciona. Si es así, podemos deshacernos de la declaración var y acortar otra línea.Rubí
fuente
%r{"(https?://[^"]+)"}
. También puede usarNet::HTTP.get('www.stroustrup.com', '/C++.html')
para acortar la solicitud (y mantenerla legible). Así código entero puede estar en una línea (manteniéndolo legible):puts Net::HTTP.get("www.stroustrup.com", "/C++.html").scan(%r{"(https?://[^"]+)"})
. Ejecúteloruby -rnet/http
y ni siquiera necesitarequire 'net/http'
línea.Haskell
Algunos problemas con
"\w"
en Text.Regex.Posixfuente
result
especifica el tipo de explícitamente? Debe estar completamente limitado por su uso enunlines
.Network.HTTP
, niTextRegex.Posix
están en elbase
paquete. (Aunque están en la Plataforma Haskell, y por supuesto en Hackage, así que ...)network
no está enbase
ninguno de los dos, así que ahorre para enrollar sus propios enlaces de socket, no hay una forma práctica de hacerlo con solobase
.PHP
Por lo que puedo decir, la mayoría de las instalaciones PHP modernas vienen con procesamiento DOM, así que aquí hay una que realmente atraviesa los anclajes dentro del HTML:
El circuito interno podría acortarse a:
fuente
1
lugar detrue
para lain_array
búsqueda estricta. También puede omitir los corchetes. No estoy completamente seguro, pero iirc también podría soltar elhttp
y solo dejar el://
(ir sin el esquema). .if ( ) {}
a favor dein_array() and print $url.PHP_EOL
. Pero sí, obtendrías otro +1 (si pudiera) para una mejor legibilidad :)@\DOMDocument
. Solo intenté eso y puedo confirmar que funciona.::loadHTMLFile()
estáticamente, y agregar@
solo oculta ese artefacto.Unix Shell
Aunque tengo que admitir que esto no funciona si hay más de un enlace en una línea.
fuente
curl http://www.stroustrup.com/C++.html
Guarda algunos caracteres.wget
es GNU (como es bash), se podría argumentar que no es un tercero. Perocurl
definitivamente es un tercero.ftp://ftp.research.att.com/pub/c++std/WP/CD2
yhttps://www.youtube.com/watch?v=jDqQudbtuqo&feature=youtu.be
?Java
fuente
Scanner
, puede hacer que procese el patrón regex para enlaces directamente e iterar sobre losScanner
resultados de.Maravilloso
fuente
SQL (SQL en cualquier lugar 16)
Definir un procedimiento almacenado para recuperar la página web.
Produzca el conjunto de resultados usando una sola consulta
Limitaciones: Esto produce hasta 256 enlaces. Si existen más enlaces, suba el 256 a un valor apropiado.
fuente
CoffeeScript / NodeJS
fuente
Perl
fuente
use v5.10;
ysay for $response->content
...say
es bastante útil y, en mi opinión, más claro aquí. (Además, ha habido muchas mejoras completamente no relacionadas con el perl6ismo en perl5 en los últimos 13 años; podría valer la pena echarle un vistazo.)say
probablemente sea más legible en este caso, particularmente para aquellos menos familiarizados con Perl.R
... aunque R está escrito principalmente en C ... así que probablemente unas pocas líneas de código C detrás de esas 2 líneas de código R.
fuente
C objetivo
fuente
Tcl
fuente
[
. Pero esa es una elección de estilo.Ir
PD: este código lee toda la fuente en la memoria, así que considera usarlo
regexp.FindReaderIndex
para buscar en stream, eso hará que la aplicación sea a prueba de balas.fuente
CJam
CJam no tiene expresiones regulares, así que tuve que usar un enfoque diferente en este:
Primero convierto todo
'
a"
, luego me divido en todos"
, tomo cada cadena alternativa y finalmente filtro esa lista para las cadenas que comienzan conhttp://
ohttps://
. Después de eso, simplemente imprima cada cadena filtrada en una nueva línea.Pruébelo utilizando el intérprete de Java como
donde file.cjam tiene el contenido del código anterior.
fuente
''/'"f/:+
para''/'"*'"/'"f/0f=
.'"f/0f=
hay? ¿Se supone que eso debe hacer algo (2%
por ejemplo)?F#
Este código podría ser mucho más corto, pero escribiría algo como esto si alguna vez esperaba tener que leer o usar este código nuevamente, por lo que tiene muchas anotaciones de tipo innecesarias. Demuestra el uso de un patrón MatchValue activo para permitir la coincidencia de patrones con el tipo estándar CLR Match
Editar hice que getLinks tenga su propia función
fuente