Estrai l'URL dal testo con più URL usando sed


4

Ho una stringa con un testo e diversi URL. Come posso estrarre un URL specifico (di un dominio specifico) con sed? Ad esempio, ho questo:

Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot

e seddeve restituire questo: http://myURL.net/files/IWANTthis


Non lo fai con grep?
Uprego

Se sai come, sì, per favore!
Tzippy,

È facile amico, fai un po 'di lavoro di prova / errore a partire da qualcosa di simile| sed s/<br \/>/<br \/>\n/g | grep "myURL\.net"
uprego

Le esatte opere dipendono dal chilometraggio completo. Se ti stai trasferendo su GNU / Linux, inizia leggendo The Art of Unix Programming di Eric S. Raymond .
Uprego

Risposte:


7

Potrebbero esserci dei problemi con sed in casi speciali. Come è stato suggerito in molti luoghi (ad esempio) - non usare regexps ma un motore di analisi html. Uno di questi parser facilmente disponibili è contenuto nel solo testo della lince del browser (disponibile su qualsiasi Linux). Quindi estrai gli URL che desideri con grep.

lynx -dump -listonly myhtmlfile.html | grep IWANTthis | sort -u

Tuttavia, ciò non funzionerà su file html alterati (non può essere analizzato correttamente) o su frammenti di testo con collegamenti. Un altro modo semplice è fare catena. Se hai un frammento di testo come il tuo in un file di testo chiamato st3.txt, puoi fare come segue:

grep http ./st3.txt | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | grep IWANTthis | sort -u

Spiegazione:

grep http ./st3.txt      => will catch lines with http from text file
sed 's/http/\nhttp/g'    => will insert newline before each http
grep ^http               => will take only lines starting with http
sed 's/\(^http[^ <]*\)\(.*\)/\1/g'   
                         => will preserve string from ^http until first space or <
grep IWANTthis           => will take only urls containing your text of interest
sort -u                  => will sort and remove duplicates from your list

Bello! Hai spiegato molto bene.
ps95,

1
Lo uso lynxanche, lo trovo utile, ma ho scoperto che in sedrealtà strappa più URL da solo poiché sednon si preoccupa della formattazione e del rispetto degli standard HTML.
A.Danischewski,

Sì, sedelabora solo il testo, non analizza affatto. Per questo motivo - per ridurre al minimo (ma non posso escluderli del tutto) tali problemi estraggo prima le linee con http in esse, faccio più linee tagliando prima di ogni http quindi abbino quelle nuove linee fino al primo spazio o parentesi angolare - poiché il collegamento ipertestuale non può contenere quelle e quindi spero di avere solo un elenco di collegamenti, da cui estraggo quelli con testo di interesse. Le interruzioni di riga all'interno degli URL potrebbero ovviamente interromperlo.
r0berts

1

È possibile utilizzare grepcon un'espressione regolare estesa (regex) per questo:

grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< '<input_string>'

Spiegazione di ciascuna parte del comando e della regex:

  • grep -Eo: Chiamiamo grepcon due opzioni.
    • -E: Abilita regex estese POSIX .
    • -o: Stampa solo le parti corrispondenti di ogni riga (senza questa opzione, per grepimpostazione predefinita viene stampata l'intera riga che contiene parti corrispondenti).
  • '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?': Questo regex è probabilmente un po 'più elaborato di quello che ti serve, quindi dovresti semplificare o rimuovere parti inutilmente complesse per i tuoi scopi. (La complessità è il risultato di un tentativo di fornire una soluzione generale.)
    • ([-+.[:alnum:]]+://)?: Corrisponde allo schema dell'URL. Il ?alla fine specifica che questo corrisponde o una volta o per niente (quindi myURL.netè abbinato anche se non viene anteposto alcuno schema). Includiamo caratteri leggermente insoliti -+.perché RFC 3986 specifica che "[s] cheme names consistono in una sequenza di caratteri che iniziano con una lettera e seguiti da qualsiasi combinazione di lettere, cifre, più ('+'), punto ('.') o trattino ('-') "(sottolineatura mia). Se sei sicuro che http://apparirà sempre di fronte myURL.net, allora puoi sostituire questa parte della regex con la semplice http://.
    • ([-[:alnum:]]+.)*: Corrisponde ai sottodomini . Alla *fine specifica che questo corrisponde a zero o più volte (in modo che i sottodomini come a.b.in a.b.myURL.netsiano abbinati). Includiamo il trattino ( -) perché RFC 1035 specifica che "[etichette del sottodominio] deve iniziare con una lettera, terminare con una lettera o una cifra e avere come caratteri interni solo lettere, cifre e trattino " (sottolineatura mia). Se sei sicuro di non aver bisogno di abbinare i sottodomini, puoi rimuovere questa parte della regex.
    • myURL.net: Questa è una corrispondenza semplice per la stringa letterale myURL.net.
    • (:[[:digit:]]+)?: Corrisponde a qualsiasi designazione della porta se è inclusa nell'URL.
    • (/[[:graph:]]*)?: Corrisponde al resto dell'URL. [:graph:]corrisponde a qualsiasi personaggio visibile.
  • <<< '<input_string>': Alimentiamo grep(che accetta un file) la nostra stringa di input usando una stringa qui . ( echo '<input_string>' |è l'alternativa comune.)

Esempio:

$ grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< 'Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot'
http://myURL.net/files/IWANTthis

Ancora una volta, la regex che ho dato sopra è probabilmente eccessivamente complicata per quello che ti serve. È necessario modificarlo in base alle proprie esigenze. Qualcosa di semplice come il seguente potrebbe funzionare:

grep -Eo 'http://myURL.net(/[[:graph:]]*)?' <<< '<input_string>'

0

Puoi usare: sed 's/<br\ *\/>/\n/g' html_file | grep myURL.net

Produzione: http://myURL.net/files/IWANTthis

Fondamentalmente sto sostituendo tutto <br />con un carattere newline e afferrando la linea pertinente con grep.

Questo non tiene conto di tutte le possibili (html consentite) varianti del <br>tag, ma gestisce quelle nel tuo esempio.


0

Puoi analizzare il file per tutti gli URL con sede quindi grepper la tua corrispondenza.

sed "s/http/\nhttp/g" your.html | sed -n "s#\(.*\)\(http.*//[a-Z0-9./-]*[^a-Z/]\)\(.*\)#\2#p;" | grep IWANTthis

Nel primo passaggio sedsostituisce tutto l'http con una newline preposta per rendere le cose più facili per sedil secondo passaggio dove sedstrappa gli URL. Questo regex generalmente funziona per me, ma potrebbe essere necessario modificarlo in base alle proprie esigenze.

Nota: è possibile farlo in un solo passaggio, ma sarà complicato con i criptici potenzialmente difficili da mantenere sedcomandi usati di rado .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.