Domanda

Sto cercando di utilizzare sed per ripulire le righe di URL per estrarre solo il dominio..

Quindi da:

http://www.suepearson.co.uk/product/174/71/3816/

Voglio:

http://www.suepearson.co.uk/

(con o senza la barra slash, non importa)

Ho provato:

 sed 's|\(http:\/\/.*?\/\).*|\1|'

e (sfuggendo al quantificatore non avido)

sed 's|\(http:\/\/.*\?\/\).*|\1|'

ma non riesco a far funzionare il quantificatore non avido, quindi finisce sempre per far corrispondere l'intera stringa.

È stato utile?

Soluzione

Né di base, né esteso Posix / GNU regex riconosce il quantificatore non avidi; hai bisogno di un'espressione regolare più tardi. Fortunatamente, Perl regex per questo contesto è abbastanza facile da ottenere:

perl -pe 's|(http://.*?/).*|\1|'

Altri suggerimenti

In questo caso specifico, è possibile ottenere il lavoro fatto senza usare un espressione regolare non avidi.

Prova questo non avido regex [^/]* invece di .*?:

sed 's|\(http://[^/]*/\).*|\1|g'

Con sed, di solito implemento la ricerca non avida cercando qualsiasi cosa tranne il separatore fino al separatore :

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'

Produzione:

http://www.suon.co.uk

questo è:

  • non emettere -n
  • cercare, abbinare il modello, sostituire e stampare s/<pattern>/<replace>/p
  • utilizzo ; cerca separatore di comandi invece di / per rendere più semplice la digitazione s;<pattern>;<replace>;p
  • ricorda la corrispondenza tra parentesi \( ... \), successivamente accessibile con \1,\2...
  • incontro http://
  • seguito da qualsiasi cosa tra parentesi [], [ab/] significherebbe entrambi a O b O /
  • Primo ^ In [] significa not, quindi seguito da qualsiasi cosa tranne la cosa in []
  • COSÌ [^/] significa tutto tranne / carattere
  • * è ripetere il gruppo precedente così [^/]* significa caratteri tranne /.
  • finora sed -n 's;\(http://[^/]*\) significa cercare e ricordare http://seguito da qualsiasi carattere tranne / e ricorda cosa hai trovato
  • vogliamo cercare fino alla fine del dominio, quindi fermati al successivo / quindi aggiungine un altro / alla fine: sed -n 's;\(http://[^/]*\)/' ma vogliamo far corrispondere il resto della riga dopo il dominio, quindi aggiungi .*
  • ora la partita ricordata nel girone 1 (\1) è il dominio, quindi sostituisci la riga corrispondente con il materiale salvato nel gruppo \1 e stampa: sed -n 's;\(http://[^/]*\)/.*;\1;p'

Se desideri includere una barra rovesciata anche dopo il dominio, aggiungi un'altra barra rovesciata nel gruppo da ricordare:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'

produzione:

http://www.suon.co.uk/

sed non supporta operatore "non avidi".

Si deve usare "[]" operatore di escludere "/" dalla partita.

sed 's,\(http://[^/]*\)/.*,\1,'

P.S. non v'è alcuna necessità di backslash "/".

Simulazione pigro (non-greedy) di quantificazione in sed

e tutti gli altri sapori regex!

  1. Trovare prima occorrenza di un'espressione:

    • POSIX ERE (utilizzando l'opzione -r)

      Regex:

      (EXPRESSION).*|.
      

      Sed:

      sed -r "s/(EXPRESSION).*|./\1/g" # Global `g` modifier should be on
      

      Esempio (trovando prima sequenza di cifre) demo live :

      $ sed -r "s/([0-9]+).*|./\1/g" <<< "foo 12 bar 34"
      
      12
      

      Come funziona

      Questa regex beneficia di un | alternanza. Ad ogni motore di posizione cercherà il primo lato di alternanza (il nostro obiettivo) e se non è abbinato secondo lato di alternanza che ha un . puntino corrisponde al carattere successivo immediato.

        

       entrare descrizione dell'immagine qui

      Dal flag globale è impostato, il motore cerca di continuare a carattere corrispondenti per carattere fino alla fine della stringa di input o il nostro obiettivo. Non appena il primo ed unico gruppo di cattura di lato sinistro di alternanza corrisponde (EXPRESSION) resto della linea viene consumato subito pure .*. Ora riteniamo che il nostro valore nel primo gruppo di acquisizione.

    • POSIX BRE

      Regex:

      \(\(\(EXPRESSION\).*\)*.\)*
      

      Sed:

      sed "s/\(\(\(EXPRESSION\).*\)*.\)*/\3/"
      

      Esempio (trovando prima sequenza di cifre):

      $ sed "s/\(\(\([0-9]\{1,\}\).*\)*.\)*/\3/" <<< "foo 12 bar 34"
      
      12
      

      Questo è come la versione ERE ma senza alternanza coinvolti. È tutto. Ad ogni singola posizione del motore di prova a corrispondere una cifra.

        

       entrare descrizione dell'immagine qui

      Se si trova, altri seguenti cifre vengono consumati e catturati e il resto della linea è abbinato immediatamente diversamente dal mezzo * più o pari a zero salta sul secondo cattura \(\([0-9]\{1,\}\).*\)* gruppo e arriva ad un punto . per indicare un singolo carattere e questo processo continua.

  2. Trovare prima occorrenza di un delimitato espressione:

    Questo approccio corrisponderà la prima occorrenza di una stringa delimitata. Possiamo chiamarlo un blocco di stringa.

    sed "s/\(END-DELIMITER-EXPRESSION\).*/\1/; \
         s/\(\(START-DELIMITER-EXPRESSION.*\)*.\)*/\1/g"
    

    stringa di input:

    foobar start block #1 end barfoo start block #2 end
    

    -EDE: end

    -SDE: start

    $ sed "s/\(end\).*/\1/; s/\(\(start.*\)*.\)*/\1/g"
    

    Output:

    start block #1 end
    

    In primo luogo le partite regex \(end\).* e cattura prima estremità delimitatore end e succedanei tutti i match con i recenti personaggi catturati che è il delimitatore fine. In questa fase la nostra produzione è: foobar start block #1 end

    .
      

     entrare descrizione dell'immagine qui

    Poi il risultato è passato al secondo \(\(start.*\)*.\)* regex che è lo stesso come la versione POSIX BRE sopra. Esso corrisponde a un singolo carattere se delimitatore inizio start non corrisponde altrimenti che corrisponda e cattura il delimitatore di inizio e corrisponde al resto di caratteri.

      

     entrare descrizione dell'immagine qui


Direttamente rispondere alla tua domanda

Utilizzando l'approccio # 2 (espressione delimitato) è necessario selezionare due espressioni appropriate:

  • EDE: [^:/]\/

  • SDE: http:

Utilizzo:

$ sed "s/\([^:/]\/\).*/\1/g; s/\(\(http:.*\)*.\)*/\1/" <<< "http://www.suepearson.co.uk/product/174/71/3816/"

Output:

http://www.suepearson.co.uk/

Soluzione non avidi di più di un singolo carattere

Questo thread è molto vecchio ma suppongo la gente ancora ne ha bisogno. Diciamo che si desidera per uccidere tutto fino alla prima occorrenza di HELLO. Non si può dire [^HELLO] ...

Quindi, una bella soluzione comporta due fasi, partendo dal presupposto che si può risparmiare una parola unica che non si aspettava nell'input, dicono top_sekrit.

In questo caso si può:

s/HELLO/top_sekrit/     #will only replace the very first occurrence
s/.*top_sekrit//        #kill everything till end of the first HELLO

Naturalmente, con un ingresso più semplice si potrebbe usare una parola più piccola, o forse anche un singolo carattere.

HTH!

Questo può essere fatto utilizzando taglio:

echo "http://www.suepearson.co.uk/product/174/71/3816/" | cut -d'/' -f1-3

sed - corrispondenza non avido da Christoph Sieghart

Il trucco per ottenere corrispondenza non avidi sed è quello di abbinare tutti i caratteri escludendo quella che termina la partita. Lo so, un gioco da ragazzi, ma ho perso minuti preziosi su di esso e gli script di shell dovrebbe essere, dopo tutto, semplice e veloce. Quindi, nel caso in cui qualcun altro potrebbe averne bisogno:

corrispondente Greedy

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

corrispondente non avido

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar

un altro modo, non usare espressioni regolari, è quello di utilizzare i campi / metodo delimitatore ad esempio

string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"

sed ha certamente il suo posto, ma questo non non è uno di loro!

Come Dee ha sottolineato: Basta usare cut. E 'molto più semplice e molto più sicuro in questo caso. Ecco un esempio in cui si estrae varie componenti della URL utilizzando la sintassi di Bash:

url="http://www.suepearson.co.uk/product/174/71/3816/"

protocol=$(echo "$url" | cut -d':' -f1)
host=$(echo "$url" | cut -d'/' -f3)
urlhost=$(echo "$url" | cut -d'/' -f1-3)
urlpath=$(echo "$url" | cut -d'/' -f4-)

ti dà:

protocol = "http"
host = "www.suepearson.co.uk"
urlhost = "http://www.suepearson.co.uk"
urlpath = "product/174/71/3816/"

Come si può vedere si tratta di un sacco approccio più flessibile.

(tutto il credito a Dee)

C'è speranza ancora per risolvere questo utilizzando puro (GNU) sed. Nonostante questa non è una soluzione generica, in alcuni casi è possibile utilizzare "loop" per eliminare tutte le parti inutili della stringa in questo modo:

sed -r -e ":loop" -e 's|(http://.+)/.*|\1|' -e "t loop"
  • -r: Usa espressione regolare estesa (per + e parentesi escape)
  • ": ciclo": definire una nuova etichetta chiamata "loop"
  • -e: aggiungere comandi a sed
  • "t ciclo": torna indietro di etichettare "loop" se ci fosse una sostituzione successo

L'unico problema qui è sarà anche tagliare l'ultimo carattere di separazione ( '/'), ma se si ha realmente bisogno è ancora possibile semplicemente rimetterlo dopo il "loop" finito, basta aggiungere questo comando supplementare alla fine della linea di comando precedente:

-e "s,$,/,"
sed 's|(http:\/\/[^\/]+\/).*|\1|'

sed -e interpreta le espressioni regolari come esteso (moderne) le espressioni regolari

Aggiornamento:. -E su MacOS X, -r in GNU sed

Perché lei ha dichiarato in particolare si sta cercando di usare sed (invece di perl, taglio, ecc), provare il raggruppamento. Questo elude l'identificatore non avido potenzialmente non essere riconosciuto. Il primo gruppo è il protocollo (vale a dire 'http: //', 'https: //', 'tcp: //', ecc). Il secondo gruppo è il dominio:

echo "http://www.suon.co.uk/product/1/7/3/" | sed "s|^\(.*//\)\([^/]*\).*$|\1\2|"

Se non hai familiarità con il raggruppamento, avviare qui .

Mi rendo conto che questo è un vecchio ingresso, ma qualcuno potrebbe trovare utile. Come il nome di dominio completo non può superare una lunghezza totale di 253 caratteri sostituirlo. * Con. \ {1, 255 \}

Questo è come fare robusto corrispondenza non avido di stringhe multi-carattere utilizzando sed. Diciamo che si desidera cambiare ogni foo...bar per <foo...bar> così per esempio questo ingresso:

$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV

dovrebbe diventare questa uscita:

ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

Per fare questo si converte foo e bar ai singoli caratteri e quindi utilizzare la negazione di quei personaggi tra di loro:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

In quanto sopra:

  1. s/@/@A/g; s/{/@B/g; s/}/@C/g è la conversione { e } a segnaposto stringhe che non può esistere in ingresso in modo da quei caratteri quindi sono a disposizione per la conversione foo e bar a.
  2. s/foo/{/g; s/bar/}/g è la conversione rispettivamente foo e bar a { e }
  3. s/{[^{}]*}/<&>/g sta eseguendo l'op che vogliamo - la conversione foo...bar a <foo...bar>
  4. s/}/bar/g; s/{/foo/g è la conversione { e } torna a foo e bar.
  5. s/@C/}/g; s/@B/{/g; s/@A/@/g è la conversione delle stringhe segnaposto di nuovo ai loro caratteri originali.

Si noti che quanto sopra non si basa su alcun particolare stringa non è presente in ingresso in quanto produce tali stringhe nel primo passo, né cura quale occorrenza di una particolare espressione regolare che si desidera abbinare dato che è possibile utilizzare {[^{}]*} come tante volte quanto necessario nell'espressione per isolare la partita reale che si desidera e / o con SED numerico operatore partita, ad esempio, sostituire solo il 2 ° evento:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV

Non ho ancora visto questa risposta, ecco come si può fare questo con vi o vim:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

Questo esegue la sostituzione vi :%s globale (la g finale), evita di generare un errore se il modello non viene trovato (e), quindi salva le conseguenti modifiche sul disco e si chiude. Il &>/dev/null impedisce l'interfaccia grafica da lampeggiante brevemente sullo schermo, che può essere fastidioso.

Mi piace usare vi a volte per regex super-complicate, perché (1) Perl è morti morire, (2) Vim ha un molto motore regex avanzate, e (3 ) sono già intimamente familiare con le regex vi nei miei modifica dei documenti utilizzo giorno per giorno.

echo "/home/one/two/three/myfile.txt" | sed 's|\(.*\)/.*|\1|'

don fastidio, ho ottenuto su un altro forum:)

sed 's|\(http:\/\/www\.[a-z.0-9]*\/\).*|\1| lavora troppo

Un'altra versione sed:

sed 's|/[:alphanum:].*||' file.txt

Si abbina / seguito da un carattere alfanumerico (quindi non un altro slash), così come il resto di caratteri fino alla fine della linea. Successivamente si sostituisce con nulla (cioè. Elimina.)

Qui è qualcosa che si può fare con un approccio in due fasi e awk:

A=http://www.suepearson.co.uk/product/174/71/3816/  
echo $A|awk '  
{  
  var=gensub(///,"||",3,$0) ;  
  sub(/\|\|.*/,"",var);  
  print var  
}'  
  

Output:    http://www.suepearson.co.uk

Speranza che aiuta!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top