Stroustrup hat kürzlich eine Reihe von Posts veröffentlicht, in denen beliebte Mythen über C ++ entlarvt werden . Der fünfte Mythos lautet: „C ++ ist nur für große, komplizierte Programme“. Um es zu entlarven, schrieb er ein einfaches C ++ - Programm, das eine Webseite herunterlud und Links daraus extrahierte . Hier ist es:
#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;
}
}
Zeigen wir Stroustrup, was für ein kleines und lesbares Programm das ist.
- Herunterladen
http://www.stroustrup.com/C++.html
Alle Links auflisten:
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 ...
Sie können eine beliebige Sprache verwenden, Bibliotheken von Drittanbietern sind jedoch nicht zulässig.
Gewinner
Die C ++ - Antwort, die durch Stimmen gewonnen wurde, basiert auf einer Bibliothek eines halben Drittanbieters (die von den Regeln nicht zugelassen ist) und zusammen mit einem anderen engen Konkurrenten, Bash , auf einem gemeinsam gehackten HTTP-Client (dies funktioniert nicht mit HTTPS). gzip, Weiterleitungen usw.). Damit ist Wolfram ein klarer Sieger. Eine andere Lösung, die in Bezug auf Größe und Lesbarkeit sehr nahe kommt, ist PowerShell (mit Verbesserungen gegenüber Kommentaren), die jedoch nicht viel Aufmerksamkeit erhalten hat. Mainstream-Sprachen ( Python , C # ) kamen auch ziemlich nahe.
Content-Type: text/html; charset=UTF-8
... Ich werde ihm eine E-Mail schicken.boost/asio
es aufgebraucht ist , was ist eine Drittanbieter - Bibliothek. Ich meine, wie werden Sprachen, die URL / TCP-Abruf als Teil ihrer Standardbibliothek nicht enthalten, konkurrieren?Antworten:
Wolfram
Das fühlt sich an wie völliges Betrügen
Fügen Sie einfach ehrliches Parsen hinzu
quelle
C ++
Das größte Manko ist die peinliche Art von boost :: asio. Ich bin mir sicher, dass es mit einer besseren Bibliothek noch kürzer sein kann.
quelle
import urllib2
C3 istusing System.Net
, Haskel möglicherweise noch immerimport Network.HTTP
, aber ein C ++ - Codierer muss Entschuldigungen dafür#include <boost/asio.hpp>
vorbringen, als ob er einen metrischen Crapton spezialisierter, zweckgebauter C ++ - (und C!) - Bibliotheken hätte Zur Auswahl steht etwas,System.Net
wird nicht erzwungen, es ist nur eine hochwertige Bibliothek, die alle in der Sprache enthaltenen .NET-Empfehlungen befolgt . Es gibt alternative Implementierungen, aber die HTTP-Unterstützung in der Standardbibliothek bedeutet, dass das Schreiben einfacher Apps einfach ist, eine bessere Interoperabilität zwischen Bibliotheken von Drittanbietern bedeutet, weniger Abhängigkeiten, eine einfache Implementierung für Fassaden usw. Stellen Sie sich eine Welt ohne vorstd::string
, wie jeder sie nutzt Stellen Sie sich alle Schwierigkeiten vor, die damit einhergehen.urllib2
ist nicht 3rd Party. Es ist in stdlib wie<iostream>
in C ++.urllib2
in Python ist im Gegensatz zu C ++ immer verfügbar<boost/asio.hpp>
. Wenn wir Module von Drittanbietern verwenden dürften; Ich würdelxml
oderBeautifulSoup
in Python verwenden.Pure Bash unter Linux / OS X (keine externen Dienstprogramme)
HTTP-Client-Software ist notorisch aufgebläht. Wir wollen solche Abhängigkeiten nicht. Stattdessen können wir die entsprechenden Header in einem TCP-Stream ablegen und das Ergebnis lesen. Es müssen keine archaischen Hilfsprogramme wie grep oder sed aufgerufen werden, um das Ergebnis zu analysieren.
Meh - ich nehme an, es könnte besser lesbar sein ...
quelle
mapfile
:)mapfile
kommt mit Bash 4.x. Dasselbe ist auch mit einerwhile read
Schleife möglich.while read
anstattmapfile
. Tragbarer und lesbarer, denke ich.Python 2
Lahm, aber funktioniert
quelle
l = re.findall('"((http)s?://.*?)"', u.urlopen(s).read())
urlopen()
. B. von ). Was sollte es mit einer solchen Ausnahme tun, außer abstürzen und sterben? Wenn es trotzdem abstürzt und stirbt, warum sollte Python nicht einfach das Abstürzen und Sterben bewältigen und die Ausnahmebehandlung ganz weglassen?urlopen
Fehler als (sagen wir) sie fangen und rufensys.exit("something's borked!")
. Wenn sie Letzteres tun, muss ich fangenSystemExit
, was nie Spaß macht.C #
quelle
var html
und wahrscheinlich verwendenvar match
, um ein paar Zeichen zu rasieren.html
Variable auch ganz entfernen , aber das ist nicht das, wonach ich suche.var
wenn sich dies nicht auf die Codesemantik auswirkt?"Kein Dritter" ist ein Irrtum
Ich denke, dass die Annahme, dass kein Dritter beteiligt ist, ein Trugschluss ist. Und es ist ein spezifischer Irrtum, der C ++ - Entwickler betrifft, da es so schwierig ist, wiederverwendbaren Code in C ++ zu erstellen. Wenn Sie überhaupt etwas entwickeln, selbst wenn es sich um ein kleines Skript handelt, verwenden Sie immer den wiederverwendbaren Code, der Ihnen zur Verfügung steht.
In Sprachen wie Perl, Python, Ruby (um nur einige zu nennen) ist die Wiederverwendung des Codes eines anderen nicht nur einfach, sondern es ist auch so, wie die meisten Leute den Code die meiste Zeit tatsächlich schreiben.
C ++, mit seinen fast unmöglich zu wartenden kompatiblen ABI-Anforderungen, macht dies zu einer viel härteren Aufgabe. Am Ende haben Sie ein Projekt wie Boost, das eine ungeheure Sammlung von Code darstellt und nur sehr wenig komponierbar ist.
Ein CPAN-Beispiel
Nur zum Spaß finden Sie hier ein CPAN-basiertes Beispiel mit einer korrekten Syntaxanalyse des HTML-Codes, anstatt zu versuchen, Regex zum Parsen des HTML-Codes zu verwenden
quelle
UNIX-Shell
Findet auch einen
ftp://
Link :)Ein anderer Weg, ohne sich auf die
://
Syntax zu verlassen:quelle
lynx
dies in diesem Szenario funktional einer Drittanbieter-Bibliothek entspricht.CSS 3
Dieser Code kann als Benutzerstil verwendet werden, um nur absolute Links auf einer Seite in einer unformatierten Liste anzuzeigen. Möglicherweise funktioniert es nicht richtig, wenn Ihr Browser die Mindestschriftgröße erzwingt.
Es funktioniert korrekt mit
http://www.stroustrup.com/C++.html
(Anmerkung!important
anbackground
). Um auf anderen Seiten mit mehr Stilen arbeiten zu können, muss diese erweitert werden (mehr Eigenschaften zurücksetzen, Eigenschaften als wichtig markieren usw.).Alternative Version, die relative Links enthält, mit Ausnahme von Intrapage-Links, die mit Hashes beginnen (sie basieren leider auf einem fest codierten absoluten Link):
quelle
Clojure
quelle
spit
,zipper
undlazy-cat
... :-)Emacs Lisp
quelle
Scala
quelle
ftp://ftp.research.att.com/pub/c++std/WP/CD2
?PHP 5
quelle
'/"((http)s?://.*?)"/'
⇒'|"((http)s?://.*?)"|'
(derzeit ein Fehler); entfernenarray_unshift($m);
(derzeit ein Fehler, den Sie wahrscheinlicharray_shift
stattdessen gemeint haben );print_r($m);
⇒print_r($m[1]);
(nur die URLs ausgeben).Power Shell
Textsuche für alle vollqualifizierten URLs (einschließlich JavaScript, CSS usw.):
Oder um Links nur in Ankertags abzurufen (einschließlich relativer URLs):
Kürzere Versionen von Kommentaren:
quelle
iwr
ist ein Alias fürInvoke-WebRequest
(PS3 +).(iwr "http://www.stroustrup.com/C++.html").Links.href
(oder(iwr "http://www.stroustrup.com/C++.html").Links.href-match":"
nur für absolute URIs)D
quelle
| sort | uniq
oder stattdessen hinzufügenimport std.array
und ändern Sie die Zeile.filter!("a")){ writeln(_.front[1]); }
in diese:.filter!("a").map!(a => a.front[1]).array.sort.uniq){ writeln(_); }
. Beachten Sie jedoch, dass ich diesen Code nur ausprobiert habe und nicht bewiesen habe, dass er korrekt oder "idiomatisch" ist. :)Node.js
quelle
require('http').get
funktioniert. Wenn dies der Fall ist, können wir die var-Anweisung verwerfen und eine weitere Zeile kürzen.Rubin
quelle
%r{"(https?://[^"]+)"}
. Sie können auch verwendenNet::HTTP.get('www.stroustrup.com', '/C++.html')
, um die Anforderung zu verkürzen (und lesbar zu halten). So gesamte Code kann in einer Zeile (wobei es lesbar):puts Net::HTTP.get("www.stroustrup.com", "/C++.html").scan(%r{"(https?://[^"]+)"})
. Führen Sie es mitruby -rnet/http
und Sie brauchen nicht einmalrequire 'net/http'
Leitung.Haskell
Einige Probleme mit
"\w"
in Text.Regex.Posixquelle
result
explizit angegeben? Es sollte durch seine Verwendung in vollständig eingeschränkt werdenunlines
.Network.HTTP
nochTextRegex.Posix
sindbase
. (Obwohl sie in der Haskell - Plattform ist, und natürlich auf Hackage, so ...)network
ist auch nicht dabeibase
, also gibt es keine praktische Möglichkeit, es mit nur zu tunbase
.PHP
Soweit ich das beurteilen kann, kommen die meisten modernen PHP-Installationen mit DOM-Verarbeitung daher. Hier ist eine, die die Anker im HTML-Code tatsächlich durchläuft:
Die innere Schleife könnte verkürzt werden auf:
quelle
1
anstelle von verwenden . Sie können die Klammern auch weglassen. Ich bin mir nicht ganz sicher, aber ich kann Sie genauso gut fallen lassen und nur verlassen (ohne das Schema). .true
in_array
http
://
if ( ) {}
zugunsten von fallen zu lassenin_array() and print $url.PHP_EOL
. Aber ja, Sie würden eine weitere +1 (wenn ich könnte) für die beste Lesbarkeit bekommen :)@\DOMDocument
. Habe es gerade versucht und kann bestätigen, dass es funktioniert.::loadHTMLFile()
statisch aufrufen und@
nur das Artefakt ausblenden.Unix-Shell
Obwohl ich zugeben muss, dass dies nicht funktioniert, wenn mehr als ein Link in einer Zeile steht.
quelle
curl http://www.stroustrup.com/C++.html
Speichert ein paar Zeichen.wget
GNU ist (wie Bash), könnte man argumentieren, dass es nicht von Drittanbietern ist.curl
Ist aber definitiv Fremdanbieter.ftp://ftp.research.att.com/pub/c++std/WP/CD2
undhttps://www.youtube.com/watch?v=jDqQudbtuqo&feature=youtu.be
?Java
quelle
Scanner
, können Sie festlegen, dass das reguläre Ausdrucksmuster für Links direkt verarbeitet und dieScanner
Ergebnisse des Objekts durchlaufen werden .Groovy
quelle
SQL (SQL Anywhere 16)
Definieren Sie eine gespeicherte Prozedur zum Abrufen der Webseite
Erstellen Sie die Ergebnismenge mit einer einzigen Abfrage
Einschränkungen: Dies erzeugt bis zu 256 Links. Wenn weitere Links vorhanden sind, erhöhen Sie die 256 auf einen geeigneten Wert.
quelle
CoffeeScript / NodeJS
quelle
Perl
quelle
use v5.10;
undsay for $response->content
...say
sind sehr nützlich und meiner Meinung nach hier klarer. (Außerdem wurden in den letzten 13 Jahren ziemlich viele Verbesserungen an Perl5 vorgenommen, die nichts mit Perl6ismus zu tun haben. Es könnte sich lohnen, dies zu überprüfen.)say
dies in diesem Fall wahrscheinlich besser lesbar ist, insbesondere für diejenigen, die mit Perl weniger vertraut sind.R
... obwohl R hauptsächlich in C geschrieben ist ... also wahrscheinlich ein paar Zeilen C-Code hinter diesen 2 Zeilen R-Code.
quelle
Ziel c
quelle
Tcl
quelle
[
. Aber das ist eine Stilwahl.Gehen
PS: Dieser Code liest die gesamte Quelle in den Speicher ein. Verwenden Sie daher die Option
regexp.FindReaderIndex
, um im Stream zu suchen, damit die App kugelsicher ist.quelle
CJam
CJam hat keinen regulären Ausdruck, daher musste ich in diesem einen anderen Ansatz verwenden:
Ich konvertiere zuerst alles
'
in"
, teile dann alles auf"
, nehme jede alternative Zeichenfolge und filtere diese Liste schließlich nach Zeichenfolgen, die mithttp://
oder beginnenhttps://
. Danach drucken Sie einfach jede gefilterte Zeichenfolge in eine neue Zeile.Probieren Sie es mit dem Java-Interpreter wie
Dabei hat file.cjam den Inhalt des obigen Codes.
quelle
''/'"f/:+
für''/'"*'"/'"f/0f=
.'"f/0f=
da? Soll das (2%
zum Beispiel) etwas bewirken?F #
Dieser Code könnte viel kürzer sein, aber ich würde so etwas schreiben, wenn ich jemals erwartet hätte, diesen Code wieder lesen oder verwenden zu müssen, damit er viele unnötige Typanmerkungen enthält. Es wird die Verwendung eines aktiven Muster- MatchValue demonstriert , um das Muster-Matching gegen den Standard-CLR-Typ Match zu ermöglichen
Edit Ich habe getLinks zu einer eigenen Funktion gemacht
quelle