@lala chiesto di entrare Come si può usare la sostituzione regex <*>? sull'afferrare URL da HTML . Ecco qualche dettaglio in più su tre risposte proposte. Innanzitutto, la dichiarazione di non responsabilità: nessuno di questi esempi esegue un corretto lavoro di analisi dell'HTML, quindi tutti possono trovare URL che non sono realmente presenti e perdere altri URL che sono realmente presenti.
/*
THIS IS NOT AN HTML PARSER
HTML parsers are hard to write. There are better ways.
Neither of these JSL ideas can properly skip comments or
many other HTML tags that should be skipped. They will
find things they shouldn't and miss other things they
should find. They've only been minimally tested on one site.
This code is presented as "how can I use contains() vs patmatch()
to efficiently work through a large string looking for something?"
The second example is FIVE TIMES FASTER and a LITTLE MORE ACCURATE.
The third example uses text explorer to grab links. I don't think
there is a pre-existing regex for the link text descriptions. It works
very similar to this code; it is NOT an HTML parser either.
If you can use python, you might want to investigate "beautiful soup".
I've not used it, but believe it addresses the "hard to write" issue.
*/
I problemi nell'analisi dell'HTML riguardano principalmente la ricerca di tag iniziali e finali corrispondenti e l'osservazione dei dati tra di essi. Tutto il JSL qui presentato può essere violato dalle funzionalità HTML. Ma potrebbe essere abbastanza buono; fai i tuoi test. Vedi anche Bella zuppa che potrebbe essere una risposta migliore.
Ecco uno snip di una pagina web HTML che mostra un link (il tag ) con un URL (la parte href=) e un po' di testo (la parte Discussions) che sarà visibile sulla pagina.
< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text< a > tag with URL and Text< a > tag con URL e testo
L'obiettivo è creare una tabella di dati degli URL e del testo del collegamento, uno per riga. Una tipica pagina web può avere circa 100 collegamenti ed essere mezzo megabyte di testo. Uno lento Il modo per attaccare il problema (non mostrato) è scrivere una semplice regex che trova un collegamento alla volta, rimuovere il collegamento dal testo e ripetere finché non se ne trova più. Se ce ne sono solo uno o due, ottimo. Ma se ce ne possono essere centinaia, allora vengono manipolate e cercate alcune centinaia di megabyte di dati.
Un modo più veloce è cercare tra i dati, andando sempre avanti, costruendo la tabella dei dati man mano che vengono trovati i collegamenti. Il primo esempio usa la funzione contains() che ha un terzo argomento per specificare una posizione iniziale. Contains() restituisce anche una posizione trovata. Aggiornando la posizione iniziale appena oltre la posizione trovata, contains() può esaminare in modo efficiente il testo senza dover eseguire il backup o modificare il testo.
u = "https://community.jmp.com/t5/Discussions/bd-p/discussions";
txt = Load Text File( u );
// a link on a page has at least two parts:
// the URL and some descriptive text.
// <A ...="" href="https://community.jmp.com/url" ...="" target="_blank"> descripton </A>
// p1 p4 p5
// using contains and regex. "<A>", p1 + 3 ); // find the end of the opening tag
p5 = Contains( txt, "</A>", p4 + 1 ); // find the ending tag
if( p5 > p4, // as long as the end is not zero, we found one, see break() below
desc = Substr( txt, p4 + 1, p5 - p4 - 1 ); // the visible link description. Images can be here too.
desc = Regex( desc, "<[^>]*>", "", globalreplace ); // remove span, image, etc tags
linktext = Substr( txt, p1, p4 - p1 + 1 ); // <A href="https://community.jmp.com/" target="_blank">
hreftext = Regex( linktext, "href\s*=\s*(\!"|')(.*?)(\1)", "\2" );// use regex to get the href value
if( !Is Missing( hreftext ), // sometimes there isn't one
dt << addrows( 1 );
irow = N Rows( dt );
dt:link[irow] = hreftext;
dt:description[irow] = desc;
);
, // else
Break() // no more end tags. there is maybe a mess of javascript.
);
pos = Max( pos, p5 + 3 ); // advance past the one just found
);
stoptime = Tick Seconds();
dt << endDataUpdate;
Show( stoptime - starttime ); </A>
Il cuore di quel codice è la linea
while( (p1 = Contains( txt, "<A></A>
che sta facendo un sacco di lavori: usa pos nel terzo argomento per saltare qualsiasi lavoro precedente, trova il prossimo Non abbiamo trovato nulla , quindi il ciclo si interrompe. La riga successiva
p4 = Contains( txt, ">", p1 + 3 );
cerca la corrispondenza > che termina il tag
p5 = Contains( txt, "", p4 + 1 );
p5 punterà al tag che termina il testo del collegamento. Molti, ma non tutti, i tag HTML funzionano così, un tag di inizio senza la / e un tag di fine con la barra. A volte il tag iniziale e quello finale sono gli stessi, utilizzando , ma questo JSL ignora questa possibilità.
L'istruzione if determina se è stato trovato qualcosa e, in tal caso, raccoglie la descrizione in questo modo
desc = Substr( txt, p4 + 1, p5 - p4 - 1 );
p4 e p5 indicano > e <. quindi p4+1 è il primo carattere della descrizione e p5-p4-1 è la lunghezza della descrizione. La riga successiva ripulisce la descrizione rimuovendo i tag incorporati
desc = Regex( desc, "<[^>]*>", "", globalreplace );
GlobalReplace significa che la regex troverà il modello, sostituendo quel testo con niente, il maggior numero di volte possibile. Il modello corrisponde a <, seguito da zero o più caratteri che non sono >, seguito da > che potrebbe essere un tag 
o un mucchio di tag di stile del testo. Il risultato finale è il testo del tag senza alcuna immagine/colore/carattere/ecc.
Le due righe successive sono simili, per afferrare l'URL piuttosto che la descrizione
p1 e p4 (vedi commento) sono le intere posizioni dei tag di collegamento; linktext è il tag di collegamento che include un numero di bit indesiderati. hreftext utilizza regex() per estrarre solo l'URL tra le virgolette href o gli apostrofi. Il modello regex usa il backref \1 per assicurarsi che l'apostrofo finale o le virgolette corrispondano a quello iniziale. La prima parentesi aperta nel modello regex crea un gruppo di acquisizione (per \1) che corrisponde a " o '. La seconda parentesi aperta è il gruppo di acquisizione (per \2) che corrisponde, avanzando con riluttanza quanto necessario per la corrispondenza tra i delimitatori. La terza parentesi aperta è il gruppo di acquisizione 3; i genitori e il raggruppamento non sono realmente necessari. Il risultato, \2, è solo l'URL.
Tutto tranne che fatto: se c'è una descrizione, aggiungi una riga alla tabella e poi, molto importante, fai avanzare la variabile pos!
Max si assicura che non vada all'indietro alla fine e rimanga bloccato in un loop.
Il codice sopra è abbastanza veloce, ma questo è ancora meglio.