2013-02-15 12 views
8

Sto provando a scrivere uno script sed che catturerà tutti gli URL "nudi" in un file di testo e li sostituiremo con <a href=[URL]>[URL]</a>. Con "nudo" intendo un URL che non è racchiuso all'interno di un tag di ancoraggio.L'espressione regolare sed può simulare lookbehind e lookahead?

Il mio pensiero iniziale era che dovevo associare gli URL che non hanno un "o un> davanti a loro, e inoltre non hanno un < o un" dopo di loro. Tuttavia, mi imbatto in difficoltà nell'esprimere il concetto di "non avere davanti o dietro" perché, per quanto ne so, sed non ha look-ahead o look-behind.

Input Esempio:

[Beginning of File]http://foo.bar arbitrary text 
http://test.com other text 
<a href="http://foobar.com">http://foobar.com</a> 
Nearing end of file!!! http://yahoo.com[End of File] 

Esempio di output desiderato:

[Beginning of File]<a href="http://foo.bar">http://foo.bar</a> arbitrary text 
<a href="http://test.com">http://test.com</a> other text 
<a href="http://foo.bar">http://foo.bar</a> 
Nearing end of file!!! <a href="http://yahoo.com">http://yahoo.com</a>[End of File] 

osservi che la terza linea è modificato, perché è già dentro <a href>. D'altra parte, sia la prima che la seconda riga sono state modificate. Infine, osserva che tutto il testo non URL non è modificato.

In definitiva, sto cercando di fare qualcosa di simile:

sed s/[^>"](http:\/\/[^\s]\+)/<a href="\1">\1<\/a>/g 2-7-2013 

ho cominciato verificando che la seguente vi correttamente abbinare e rimuovere un URL:

sed 's/http:\/\/[^\s]\+//g' 

Allora ho provato questo, ma è non è in grado di eguagliare gli URL che iniziano all'inizio del file/input:

sed 's/[^\>"]http:\/\/[^\s]\+//g' 

È lì E un modo per aggirare questo problema in sed, simulando lookbehind/lookahead, o abbinando in modo esplicito l'inizio del file e la fine del file?

+0

Perché usate '[^ \>"] '? – texasbruce

+0

Sto cercando un URL che non è preceduta da virgolette o un segno di maggiore. – merlin2011

+0

Non sfuggire alla'> ' – texasbruce

risposta

4

sed è un ottimo strumento per semplici sostituzioni su una sola riga, per qualsiasi altro problema di manipolazione del testo basta usare awk.

Controllare la definizione che sto utilizzando nella sezione BEGIN di seguito per un'espressione regolare che corrisponde agli URL. Funziona per il tuo campione ma non so se cattura tutti i possibili formati di URL. Anche se così non fosse, potrebbe essere adeguato alle tue esigenze.

$ cat file 
[Beginning of File]http://foo.bar arbitrary text 
http://test.com other text 
<a href="http://foobar.com">http://foobar.com</a> 
Nearing end of file!!! http://yahoo.com[End of File] 
$ 
$ awk -f tst.awk file 
[Beginning of File]<a href="http://foo.bar">http://foo.bar</a> arbitrary text 
<a href="http://test.com">http://test.com</a> other text 
<a href="http://foobar.com">http://foobar.com</a> 
Nearing end of file!!! <a href="http://yahoo.com">http://yahoo.com</a>[End of File] 
$ 
$ cat tst.awk 
BEGIN{ urlRe="http:[/][/][[:alnum:]._]+" } 
{ 
    head = "" 
    tail = $0 
    while (match(tail,urlRe)) { 
     url = substr(tail,RSTART,RLENGTH) 
     href = "href=\"" url "\"" 

     if (index(tail,href) == (RSTART - 6)) { 
      # this url is inside href="url" so skip processing it and the next url match. 
      count = 2 
     } 

     if (! (count && count--)) { 
      url = "<a " href ">" url "</a>" 
     } 

     head = head substr(tail,1,RSTART-1) url 
     tail = substr(tail,RSTART+RLENGTH) 
    } 

    print head tail 
} 
+0

Nell'URL regex si utilizza '_' come carattere di nome host valido, non dovrebbe essere '-'? –

+0

Come ho detto all'inizio della risposta 'Controlla la definizione che sto usando nella sezione BEGIN sotto per un'espressione regolare che corrisponda agli URL. Funziona per il tuo campione ma non so se cattura tutti i possibili formati di URL. Non sono un esperto di sintassi URL. –

1

Il problema evidente con il vostro comando è

You did not escape the parenthesis "(" 

Questa è la cosa strana sed regex. È differente dalla regex di Perl che molti simboli sono di default "letterali". Devi fuggire da loro per "funzionare". Prova:

s/\([^>"]\?\)\(http:\/\/[^\s]\+\)/\1<a href="\2">\2<\/a>/g 
+0

Come un chiarimento, sto cercando di far corrispondere gli URL che non hanno un "o un> davanti a loro. – merlin2011

+0

@ merlin2011 Yeh modificato. – texasbruce

+0

La soluzione data non corrisponderà' http: // google.com' all'inizio di file o inizio di input – merlin2011