Appunti: parser

function processText(testo) {
	var myArray = testo.split('\n');
	for(var i in myArray) {
		var re = /^(\d\d)\/(\d\d)\/(\d\d\d\d), (\d\d\:\d\d) - ([^:]*): (.*)/;
		var op = re.exec(myArray[i]);
		if(op) { console.log(re.exec(myArray[i]));}
		else { console.log(myArray[i]);}
	}
}

Pattern multiriga

http://unix.stackexchange.com/questions/112132/how-can-i-grep-patterns-across-multiple-lines

sed -n '/capo/{:start /coda/!{N;b start};/una regex/p}' mio_file
  • -n è l’ equivalente di –quiet, –silent : sopprime la scrittura automatica del “pattern space”
  • /capo/{} cerca capo ed esegue le parentesi graffe. Sostituire capo con l’ inizio del pattern cercato.
  • :start è un’ etichetta che serve per continuare il loop finchè non si trova la fine della regex.
  • /coda/!{} esegue le parentesi graffe finchè non trova la riga che contiene coda. Sostituire coda con la fine del pattern cercato.
  • N appende la riga al buffer attivo (il pattern space di sed).
  • b start salta incondizionatamente all’ etichetta start, cioè permette di eseguire la precedente istruzione per tutte le righe che non contengono coda.
  • /una regex/p stampa il pattern cercato su più righe.

Bash: Estrarre occorrenze multiple di una regex da una linea di testo

Per estrarre occorrenze multiple di una regex da una riga di testo (ad esempio le URL da un file HTML) bisogna ricorrere ad un artificio.

Infatti il pattern “.*” è greedy, cioè va a prendere la più grande occorrenza che trova, non solamente la prima ! Ad esempio “http.*jpg” non trova il primo file, ma tutta la stringa racchiusa tra il primo “http” trovato e l’ ultimo “jpg” trovato.

L’ artificio è il seguente: spezzare la riga di testo con un carattere univoco, ed usarlo come “segnaposto” per la stringa da estrarre.
Il carattere univoco è il “newline”: \n.

Vediamo i singoli passi:

# aggiungere il carattere univoco all' inizio della stringa
# notare il simbolo &
sed 's/http:/\n&/g'
# poi eliminare tutti i caratteri diversi da \n
# notare il [^\n]* tra http e jpg !!!
# è questo ad aggirare il comportamento greedy !!!
sed 's/[^\n]*\n\(http[^\n]*\.jpg\)[^\n]*/\1\n/g'

# METTENDO TUTTO INSIEME:
cat textstring.txt | sed 's/http:/\n&/g;s/[^\n]*\n\(http[^\n]*\.jpg\)[^\n]*/\1\n/g'

Con python è più semplice: basta usare il “?” per modificare il comportamento del pattern “.*” in non-greedy e poi usare il comando findall per trovare tutte le occorrenze in una lista

import re
# notare il "?" che modifica in non-greedy:
regex=re.compile("http.*?\.jpg")
results=regex.findall(file-string)