Stroustrup opublikował ostatnio serię postów obalających popularne mity o C ++ . Piąty mit brzmi: „C ++ jest przeznaczony tylko dla dużych, skomplikowanych programów”. Aby go obalić, napisał prosty program C ++ pobierający stronę internetową i wydobywający z niej linki . Oto on:
#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;
}
}
Pokażmy Stroustrupowi, czym tak naprawdę jest mały i czytelny program.
- Pobieranie
http://www.stroustrup.com/C++.html
Wyświetl wszystkie linki:
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 ...
Możesz używać dowolnego języka, ale biblioteki innych firm nie są dozwolone.
Zwycięzca
Odpowiedź C ++ wygrana głosami, ale opiera się ona na bibliotece innej firmy (która jest niedozwolona przez zasady), a wraz z innym bliskim konkurentem Bashem opiera się na zhakowanym kliencie HTTP (nie będzie współpracować z HTTPS, gzip, przekierowania itp.). Więc Wolfram jest wyraźnym zwycięzcą. Kolejnym rozwiązaniem, które jest bardzo podobne pod względem wielkości i czytelności, jest PowerShell (z ulepszeniami wynikającymi z komentarzy), ale nie spotkał się on z dużym zainteresowaniem. Języki głównego nurtu ( Python , C # ) również były bardzo podobne.
Content-Type: text/html; charset=UTF-8
... Wyślę mu e-maila.boost/asio
stosowany jest tam, który jest biblioteką trzeciej. Mam na myśli, w jaki sposób konkurować będą języki, które nie obejmują pobierania adresów URL / TCP jako części standardowej biblioteki?Odpowiedzi:
Wolfram
To jest jak całkowite oszustwo
Więc po prostu dodaj uczciwe parsowanie na wierzchu
źródło
C ++
Główną wadą jest niezręczna natura boost :: asio, jestem pewien, że może być jeszcze krótsza z lepszą biblioteką.
źródło
import urllib2
, C3 może nadalusing System.Net
, Haskel może nadalimport Network.HTTP
, ale koder C ++ musi usprawiedliwiać,#include <boost/asio.hpp>
jak gdyby posiadał metryczny crapton specjalistycznych, specjalnie zbudowanych bibliotek C ++ (i C!) dostępne do wyboru to coś, czego można się wstydzić tylko dlatego, że komitet nie zadał sobie trudu, aby nakarmić cię konkretnym ...System.Net
nie jest wymuszony, to tylko wysokiej jakości biblioteka zgodna ze wszystkimi zaleceniami .NET zawartymi w tym języku. Istnieją alternatywne implementacje, ale obsługa HTTP w standardowej bibliotece oznacza, że pisanie prostych aplikacji jest proste, oznacza lepszą interoperacyjność między bibliotekami stron trzecich, oznacza mniej zależności, oznacza łatwą implementację fasad itp. Wyobraź sobie świat bezstd::string
, wyobraź sobie, jak wszyscy używają ich własną bibliotekę, wyobraź sobie wszystkie związane z tym trudności.urllib2
jest stroną trzecią. Jest w stdlib jak w C ++. w Pythonie jest zawsze dostępne inaczej niż w C ++. Gdybyśmy mogli używać modułów zewnętrznych; Chciałbym użyć lub w Pythonie.<iostream>
urllib2
<boost/asio.hpp>
lxml
BeautifulSoup
Pure Bash w systemie Linux / OS X (bez narzędzi zewnętrznych)
Oprogramowanie klienckie HTTP jest notorycznie nadęte. Nie chcemy tego rodzaju zależności. Zamiast tego możemy przesunąć odpowiednie nagłówki w dół strumienia TCP i odczytać wynik. Nie trzeba wywoływać archaicznych narzędzi, takich jak grep lub sed, aby przeanalizować wynik.
Meh - przypuszczam, że może być bardziej czytelny ...
źródło
mapfile
:)mapfile
pochodzi z bash 4.x. To samo jest całkowicie wykonalne zwhile read
pętlą.while read
zamiastmapfile
. Myślę, że bardziej przenośny i czytelniejszy.Python 2
Kulawy, ale działa
źródło
l = re.findall('"((http)s?://.*?)"', u.urlopen(s).read())
urlopen()
). Co powinien zrobić z takim wyjątkiem oprócz awarii i śmierci? Jeśli i tak się zawiesi i umrze, dlaczego po prostu nie pozwolić Pythonowi uporać się z awarią i umrzeć i całkowicie zrezygnować z obsługi wyjątków?urlopen
błędów niż (powiedzmy) łapał je i dzwoniłsys.exit("something's borked!")
. Jeśli zrobią to drugie, muszę złapaćSystemExit
, co nigdy nie jest zabawne.DO#
źródło
var html
i prawdopodobnie,var match
aby ogolić kilka postaci.html
całkowicie pozbywać się zmiennych, ale nie o to mi chodzi.var
gdy nie wpłynie to na semantykę kodu?„Żadna strona trzecia” jest błędem
Uważam, że założenie „braku stron trzecich” jest błędem. Jest to szczególny błąd, który dotyka programistów C ++, ponieważ tak trudno jest stworzyć kod wielokrotnego użytku w C ++. Gdy w ogóle coś opracowujesz, nawet jeśli jest to mały skrypt, zawsze będziesz korzystać z wszelkich dostępnych fragmentów kodu wielokrotnego użytku.
Chodzi o to, że w językach takich jak Perl, Python, Ruby (by wymienić tylko kilka) ponowne użycie kodu innej osoby jest nie tylko łatwe, ale tak właśnie większość ludzi faktycznie pisze kod.
C ++, ze swoimi prawie niemożliwymi do utrzymania, kompatybilnymi wymaganiami ABI, sprawia, że praca jest o wiele trudniejsza, kończy się projekt taki jak Boost, który jest monstrualnym repozytorium kodu i bardzo niewielką kompozycją poza nim.
Przykład CPAN
Dla zabawy, oto przykład oparty na CPAN, z poprawnym parsowaniem html, zamiast próby użycia wyrażenia regularnego do parsowania html
źródło
Powłoka UNIX
Znajduje również
ftp://
link :)Innym sposobem, bez polegania na
://
składni:źródło
lynx
W tym scenariuszu twierdzę, że jest funkcjonalnie równoważny bibliotece innej firmy.CSS 3
Tego kodu można użyć jako stylu użytkownika do wyświetlania wyłącznie bezwzględnych linków na stronie na niesformatowanej liście. Może nie działać poprawnie, jeśli przeglądarka wymusza minimalny rozmiar czcionki.
Działa poprawnie z
http://www.stroustrup.com/C++.html
(uwaga!important
nabackground
). Aby pracować na innych stronach z większą liczbą stylów, należy go rozszerzyć (zresetuj więcej właściwości, zaznacz właściwości jako ważne itp.).Alternatywna wersja, która zawiera linki względne, z wyjątkiem linków intrapage zaczynających się od skrótów (opiera się niestety na bezwzględnym linku bezwzględnym)
źródło
Clojure
źródło
spit
,zipper
ilazy-cat
... :-)Emacs Lisp
źródło
Scala
źródło
ftp://ftp.research.att.com/pub/c++std/WP/CD2
?PHP 5
źródło
'/"((http)s?://.*?)"/'
⇒'|"((http)s?://.*?)"|'
(obecnie błąd); usuńarray_unshift($m);
(obecnie błąd, który prawdopodobnie miałeś na myśliarray_shift
);print_r($m);
⇒print_r($m[1]);
( wysyłaj tylko adresy URL).PowerShell
Wyszukiwanie tekstowe wszystkich w pełni kwalifikowanych adresów URL (w tym JavaScript, CSS itp.):
Lub, aby uzyskać linki tylko w tagach zakotwiczonych (obejmuje względne adresy URL):
Krótsze wersje z komentarzy:
źródło
iwr
to aliasInvoke-WebRequest
(PS3 +).(iwr "http://www.stroustrup.com/C++.html").Links.href
(lub(iwr "http://www.stroustrup.com/C++.html").Links.href-match":"
tylko bezwzględnych URI)re
źródło
| sort | uniq
albo zamiast dodaćimport std.array
i zmienić linię.filter!("a")){ writeln(_.front[1]); }
do tego:.filter!("a").map!(a => a.front[1]).array.sort.uniq){ writeln(_); }
. Zauważ jednak, że wypróbowałem tylko ten kod i nie udowodniłem, że jest poprawny lub „idiomatyczny”. :)Node.js
źródło
require('http').get
działa. Jeśli tak, możemy porzucić instrukcję var i skrócić kolejną linię.Rubin
źródło
%r{"(https?://[^"]+)"}
. Możesz także użyć,Net::HTTP.get('www.stroustrup.com', '/C++.html')
aby skrócić żądanie (i zachować je do odczytu). Więc cały kod może być w jednej linii (utrzymując ją czytelny)puts Net::HTTP.get("www.stroustrup.com", "/C++.html").scan(%r{"(https?://[^"]+)"})
. Uruchom go,ruby -rnet/http
a nawet nie potrzebujeszrequire 'net/http'
linii.Haskell
Niektóre problemy z
"\w"
Text.Regex.Posixźródło
result
wyraźnie określony? Powinno być w pełni ograniczone przez jego użycie wunlines
.Network.HTTP
aniTextRegex.Posix
wbase
pakiecie. (Chociaż są na platformie Haskell i oczywiście na Hackage, więc ...)network
nie ma gobase
również, więc oszczędzaj na zwijanie własnych wiązań gniazd, nie ma praktycznego sposobu, aby to zrobić za pomocą justbase
.PHP
O ile mi wiadomo, większość nowoczesnych instalacji PHP jest wyposażona w przetwarzanie DOM, więc oto ta, która faktycznie przegląda kotwice wewnątrz HTML:
Wewnętrzną pętlę można skrócić do:
źródło
1
zamiasttrue
doin_array
ścisłego wyszukiwania. Możesz również pominąć nawiasy kwadratowe. Nie jestem do końca pewien, ale równie dobrze możesz upuścićhttp
i tylko zostawić://
(idź bez schematu). .if ( ) {}
korzyśćin_array() and print $url.PHP_EOL
. Ale tak, dostałbyś kolejne +1 (gdybym mógł) za najlepszą czytelność :)@\DOMDocument
. Właśnie to wypróbowałem i mogę potwierdzić, że działa.::loadHTMLFile()
statycznie, a dodanie@
tylko ukrywa ten artefakt.Powłoka Unix
Chociaż muszę przyznać, że to nie działa, jeśli w linii jest więcej niż jeden link.
źródło
curl http://www.stroustrup.com/C++.html
zapisuje kilka znaków.wget
jest GNU (podobnie jak bash), można argumentować, że nie jest to firma zewnętrzna. Alecurl
zdecydowanie jest to firma zewnętrzna.ftp://ftp.research.att.com/pub/c++std/WP/CD2
ihttps://www.youtube.com/watch?v=jDqQudbtuqo&feature=youtu.be
?Jawa
źródło
Scanner
, możesz zmusić go do przetwarzania wzorca wyrażeń regularnych dla linków bezpośrednio i iteracjiScanner
wyników.Groovy
źródło
SQL (SQL Anywhere 16)
Zdefiniuj procedurę przechowywaną, aby pobrać stronę internetową
Utwórz zestaw wyników za pomocą jednego zapytania
Ograniczenia: Daje to do 256 linków. Jeśli istnieje więcej linków, zwiększ 256 do odpowiedniej wartości.
źródło
CoffeeScript / NodeJS
źródło
Perl
źródło
use v5.10;
isay for $response->content
...say
są całkiem przydatne i moim zdaniem tutaj bardziej zrozumiałe. (Ponadto w ciągu ostatnich 13 lat wprowadzono wiele całkowicie niezwiązanych z perl6izmem ulepszeń w perl5; może warto sprawdzić).say
prawdopodobnie jest to bardziej czytelne w tym przypadku, szczególnie dla osób mniej zaznajomionych z perlem.R
... chociaż R jest napisany głównie w C ... więc prawdopodobnie kilka linii kodu C za tymi 2 liniami kodu R.
źródło
Cel C
źródło
Tcl
źródło
[
. Ale to wybór stylu.Iść
PS ten kod odczytuje całe źródło do pamięci, więc rozważ użycie
regexp.FindReaderIndex
wyszukiwania w strumieniu, dzięki czemu aplikacja będzie kuloodporna.źródło
CJam
CJam nie ma wyrażenia regularnego, więc w tym przypadku musiałem zastosować inne podejście:
Najpierw konwertuję wszystko
'
na"
, następnie dzielę na wszystkie"
, biorę każdy alternatywny ciąg, a następnie filtruję tę listę pod kątem ciągów rozpoczynających się odhttp://
lubhttps://
. Następnie po prostu wydrukuj każdy filtrowany ciąg w nowej linii.Spróbuj, używając interpretera Java, takiego jak
gdzie plik.cjam ma treść powyższego kodu.
źródło
''/'"f/:+
dla''/'"*'"/'"f/0f=
.'"f/0f=
tam jest ? Czy to ma coś zrobić (2%
na przykład)?FA#
Ten kod może być znacznie krótszy, ale napisałbym coś takiego, gdybym kiedykolwiek spodziewał się, że będę musiał go przeczytać lub użyć ponownie, aby zawierał wiele niepotrzebnych adnotacji typu. Pokazuje użycie aktywnego wzorca MatchValue, aby umożliwić dopasowanie wzorca do standardowego dopasowania typu CLR
Edycja Zrobiłem getLinks własną funkcję
źródło