PHP: espressioni regolari
Ho necessità di appuntare qualche dritta sulle espressioni regolari (in particolare con PCRE), causa la mia scadente memoria. Al momento è un work in progress.Convenzioni
• soggetto - stringa su cui si desidera far matchare la regex.
• regex - espressione regolare.
• engine - software che interpreta la regex sul soggetto
• matchare - verbo inglese italianizzato per indicare l'azione di "soddisfare" e "consumare" (la parte del soggetto soddisfatta).
Metacaratteri & co
• \a - bell
• \e - escape
• \f - form feed
• \n - newline
• \r - carriage return
• \t - tab
• \v - vertical tab
• \d - Una cifra fra 0-9.
• \b - Detta word boundary, è un ancora, matcha all'inizio o fine di una parola se quest'ultima è preceduta o postceduta da un non word character. Ha senso solo se nelle regex viene prima o dopo di un word character. Praticamente è come se la regex dovesse matchare \w\W o vicecersa.
• \B - Opposto di \b.
• \D - Qualsiasi carattere che non sia 0-9.
• \w - Qualsiasi word character, ossia lettera, cifra o underscore.
• \W - Qualsiasi carattere che non sia una lettera, cifra o underscore.
• \s - whitespace ossia spazio, tab e newline.
• \S - Qualsiasi carattere non matchato da \s.
• (?i) - Rende case insensitive da quel punto in poi la regex.
• (?s) - Abilita per la regex che segue la modalità "dot matches line breaks".
• (?m) - Abilita per la regex che segue la modalità "^ and $ match at line breaks".
• \Q - Rende letterale tutto quelle che segue (block escape).
• \E - Termina il block escape.
• \A - Se posto all'inizio di una regex, indica che il soggetto deve matchare la regex fin dal suo primo carattere.
• \Z - Se posto alla finw di una regex, indica che il soggetto deve matchare la regex completamente per la sua ultima parte.
• * - è un quantificatore (vedi paragrafo dedicato), indica che la regex che lo precede può ripetersi 0 o più volte nel soggetto.
• + - è un quantificatore (vedi paragrafo dedicato), indica che la regex che lo precede può ripetersi 1 o più volte nel soggetto.
• ? - è un quantificatore (vedi paragrafo dedicato), indica che la regex che lo precede può ripetersi 0 o 1 volta (ossia la rende opzionale) nel soggetto.
• $ - Se posto alla finw di una regex, indica che il soggetto deve matchare la regex completamente per la sua ultima parte. Se l'opzione "^ and $ match at line breaks" è abilitata ed è posto alla fine di una regex, ha il significato di indicare (ancora) la fine della linea (e non del soggetto).
• ^ - Se posto all'inizio di una regex, indica che il soggetto deve matchare la regex fin dal suo primo carattere. Se posto come primo carattere dentro una classe di caratteri ha il significato di negare quella classe (è matchato qualsiasi carattere non indicato nella classe). Se l'opzione "^ and $ match at line breaks" è abilitata ed è posto all'inizio di una regex, ha il significato di indicare (ancora) l'inizio della linea (e non del soggetto).
• . - Matcha ogni carattere. Di default non matcha anche il newline, occorre indicarlo esplicitamente attraverso l'opzione "dot matches line breaks".
• | - Divide la regex (o solo una parte) in alternative (es. 'cane|gatto|topo' indica che la regex matcha cane o gatto o topo). La regex matchera usando la prima alternativa valida (nell'ordine da noi indicato).
Quantificatore
E' possibile far ripetere una regex, facendola seguire da un quantificatore 'regex{min, max}' (variable ripetition). Se si omette uno due indici (compresa la vigola) '{numero}' allora la regex è ripetuta esattamente quel numero di volte (fixed ripetition). Se si omette l'indice max (lasciando la virgola) allora si impone un numero minimo di ripetizioni ma non un massimo (infinite ripetition) che corrisponde ad usare il quantificatore '*'. Se si usa 'regex{1,}' è come se si stesse usando il quantificatore '+'. Un quantificatore può presentarsi dopo un gruppo di cattura, ma sarà possibile effettura backreference solo un singolo gruppo e questo corrispondera alla parte del soggetto matchata per ultima dal (ultimo) gruppo di cattura. Un modo per catturare tutta la parte del soggetto matchata da tutti i gruppi di cattura ripetuti è quello di rendere il gruppo di cattura non più di cattura (gioco di parole) e rendere quest'ultimo, assieme al quantificatore, un gruppo di cattura (esempio vogliamo catturare un numero di 8 cifre, se prima la regex era '\d{8}', ora sarà '((?:\d)){8}' in cui '\1' ci restituira l'intero numero di 8 cifre e '\2' ci restituira solo l'ultima cifra).
Classe di caratteri
Un insieme di caratteri racchiusi fra due parentesi quadre (es. [ae]) ha il significato di creare una classe di alternative da matchare (l'esempio precedente risulterebbe valido incontrando sia una a che una e). Al suo interno è possibile inserire range di caratteri come: a-z, A-Z, 0-9.
Gruppo di cattura
Una regex (o parte di essa) racchiusa fra parentesi tonde ha la proprietà di catturare quello che matcha (per essere eventualmente usato). E' possibile usare la parte del soggetto catturato anche all'interno della stessa regex, basta indicarlo con \numero_gruppo_cattura (esempio '(\d\d)\1'), dove i gruppi di cattura sono numerati a partire da 1, nell'ordine in cui si presentano nella regex. Non ha senso richiamare un gruppo prima che esso sia stato catturato. Il richiamo è detto backreference. Se i gruppi catturati sono maggiori di 9, allora dal decimo gruppo in poi sarà '\10' (fino a 99). Ai gruppi di cattura può essere anche assegnato un nome nei seguenti modi: '(?<nome>regex)' richiamato con '\k<nome>', '(?'year'regex)' richiamato con '\k'magic'', '(?P<nome>regex)' richiamato con '(?P=nome)'. Per effettuare backrefence ad un gruppo di cattura all'esterno della regex (ad esempio durante un operazione di find & replace) è possibile utilizzare le forme '$numero_gruppo', '\numero_gruppo', e '${numero_gruppo}' ('$10', '\10' e i rispettivi successori sono sempre trattati come il decimo gruppo di cattura e mai ambiguamente come '\1' seguiti da un letterale '0'). Per effettuare backreference esternamente alla regex ad un gruppo con nome assegnato (esempio '(?<nome>.*)') è necessario usare comunque il classico backrefence numerico (esempio '\1', '$1' o '${1}').
Gruppo di non cattura
Catturare un parte del soggetto matchata è un operazione onerosa, pertanto se in alcuni casi si ha la necessità di "raggruppare" una regex ma non si ha necessità della cattura si può racchiudere la regex interessata tra '(?:' e ')'. E' possibile anche inserire dei "mode modifiers" per solo quel gruppo (esempio (?i:exp_regolare) oppure per disabilitare il mode modifier '(?-i:exp_regolare)' ).
Comportamento "greedy"
Di default ogni quantificatore matcha il maggior numero possibile di caratteri (esempio '(.*)' catturera al primo ed unico, per questa regex, tentativo tutto il soggetto). Se la regex non riuscisse al primo tentativo a matchare il soggetto allora effettuerebbe un indietreggiamento (backtracks), diminuendo di un carattere (in realtà diminuisce di una volta il matching, ossia se la regex è '(..)*\d', al primo tentativo il quantificatore matcharebbe tutto il soggetto, se composto da un numero pari di caratteri, al secondo tentivo matcharebbe tutto il soggetto esclusi i suoi ultimi due caratteri e così via) la parte del soggetto matchata dal quantificatore greedy (esempio '.*\d', al primo tentativo sicuramente fallirebbe perchè il quantificatore greedy '.*' matchare l'intero soggetto non lasciando possibilità a '\d' di matchaere un carattere numerico, così al secondo tentativo il quantificatore greedy matcherà tutto il soggetto tranne un carattere, se '\d' non risultasse matchata, allora si procederebbe ancora indietreggiando). Ad ogni passaggio dell'indietreggiamento l'engine tiene traccia di posizioni (backtracking position) a cui poter ritornare nel caso il resto della regex (che segue il quantificatore) fallisse nel tentivo di matching.
Comportamento "lazy"
E' il comportamento opposto al "greedy" per cui un quantificatore matcha il minor numero possibile di caratteri (esempio, se abilitato il comportamento "lazy", '(.*)' non catturera alcun carattere al primo tentativo). E' possibile abilitare questo comportamento ad esempio posizionando un '?' dopo un quantificatore (esempi: '*?', '+?', '??' e '{2,8}?'). Anche con il comportamento "lazy" viene effettuata l'operazione di backtracks (se necessario), solo che in modo opposto (ossia avanzando). Se dopo il primo tentativo la regex non risultasse soddisfatta, allora il lazy quantificatore si ripeterebbe (nel matching) una volta in più del precedente tentativo (anche in questo caso, l'engine tiene traccia della backtrack position).
Quantificatore possessivo e gruppo atomico
Non sempre l'operazione di "backtracks" è una cosa desiderata. Un primo valido motivo è che tale operazione, in oppurtune situazioni, può portare ad un gran numero di tentativi (che facilmente raggiunge una complessità in tempo esponenziale) da parte dell'engine per far matchare la regex sul soggetto. Esistono due metodi per evitare tale operazione: quantificatori possessivi e gruppi atomici. I quantificatori possessivi sono quantificatori seguiti da un '+' (esempio '*+'). Un quantificare possessivo non tiene traccia delle backtrack position e pertanto, per conto suo, richiedere un unica possibilità di matching per l'engine a seconda del suo comportamento greedy o lazy. Un gruppo atomico, realizzabile con '(?>regex)', è un gruppo di non cattura che, una volta matchata la parte del soggetto da esso desiderata, non tiene traccia della backtrack position. La differenza nel comportamento tra un quantificatore possessivo e un gruppo atomico è che il primo non tiene mai realmente traccia della backtrack position, al contrario il secondo ne tiene traccia ma, appena matcha la parte del soggetto desiderata, l'engine "getta" via la backtrack position. Pertanto a livello pratico (stesso risultato) non ci sono differenze nell'uso di uno rispetto all'altro (e spesso non ve ne è neanchè a livello implementativo). Quello che è importante notare è che il gruppo atomico può racchiudere un intera espressione regolare, al contrario un quantificatore possessivo è applicato solo ad un token (che però può essere un gruppo e quindi rendendolo ugualmente equivalente al suo collega). Pertanto '\w++\d++' e '(?>\w+\d+)' non sono la stessa cosa, con la prima regex il soggetto "abc123" non risulterebbe valido, in quanto '\w++' consumerebbe l'intero soggetto e '\d++' fallirebbe (nessun altro tentativo verrebbe fatto dall'engine in quanto non si è tenuto traccia di alcuna backtrack position), con la seconda e lo stesso soggetto, al primo tentativo '\w+' consumerebbe tutto il soggetto e '\d+' fallirebbe, a questo punto, l'engine, non essendo ancora "uscito" dal gruppo atomico (perchè non soddisfatto), al secondo tentativo effettuerebbe indietreggiamento per '\w+' di un carattere in modo tale che essa consumasse 'abc12' permettendo a '\d+' di venir soddisfatta con '3'.
Lookahead
Alcune volte si rende necessario controllare la presenza di alcuni caratteri senza che la regex impiegata matchi (o consumi) quest'ultimi. Tale operazione può essere svolta con un lookahead (zero-length assertion), che è realizzabile con '(?=regex)'. L'engine in presenza ad esempio di una regex del tipo '\w(?=\d).', controlla che nel soggetto sia soddisfatta '\w' (consumando la parte del soggetto che la soddisfa) successivamente entra nel lookahead controlla che sia soddisfatta '\d' (se ciò non accade la regex è dichiarata non soddisfatta) e si dimentica di quanto ha consumato per quest'ultima regex (interna al lookahead) e segue nella verifica per '.' (che parte a controllare il soggetto dove si era fermata la regex '\w'). Un lookheak può essere negato (negative lookahead) con la forma '(?!regex)'. E' importante notare che un lookahead è un gruppo atomico, una volta soddisfatto, non ricorda in alcun modo la backtrack position. E' legale inserire un gruppo di cattura dentro un lookahead e fare backreference all'esterno di esso.
Lookbehind
In analogia a quanto visto per un lookahead, un lookbehind, realizzabile con '(?<=regex)', controlla che il soggetto matchi una certa regex (senza consumarlo), attraversando il soggetto da destra verso sinistra (unico esempio). Con una regex del tipo '..(?<=\d)\w', l'engine procederà a testare il soggetto finchè non troverà soddifatta '..', a questo punto controllera che la regex contenuta all'interno del lookbehind '\d' sia soddisfatta (controllerà il carattere subito a sinistra della posizione raggiunta dalla precedente regex, ossia controllera che l'ultimo carattere consumato sia un carattere numerico) e in caso affermativo (senza consumare o comunque alterare in alcune modo lo stato delle cose presentato a seguito della prima regex '..') procedererà nel testare '\w'. Un lookbehind può essere negato con la forma '(?<!regex)'. Per una questione implementativa (è l'unica caso in cui il test di una regex procede da destra verso sinistra) non è possibile usare all'interno di un lookbehind quantificatori "infiniti" come '*','+' e '{min,}'. E' importante notare che un lookbehind è un gruppo atomico, una volta soddisfatto, non ricorda in alcun modo la backtrack position. E' legale inserire un gruppo di cattura dentro un lookbehind e fare backreference all'esterno di esso.
Espressioni condizionali
E' possibile inserire delle regex che verifichino alcune condizioni. Tale opportunità è limitata alla cattura o meno di un gruppo. La regex condizionale è realizzato con '(?(numero_gruppo_cattura)then|else)' dove la regex, ovviamente, deve possedere il gruppo di cattura di cui si vuole verificare la cattura e then/else sono regex "usate" dall'engine rispettivamente nel caso positivo della cattura o nel caso negativo (il gruppo non è stato catturato). 'then' e 'else' possono essere una qualunque regex (quindi anche omesse), purchè non contengano '|' (in questo caso è necessario creare un gruppo, ad esempio '(?(1)(cane|gatto)|(topo|lucertola))' ). E' possibile usare un espressione condizionale con un lookahead od un lookbehind (al posto della verifica sul gruppo di cattura) con la seguenti forme '(?(?=regex)then|else)' e '(?(?<=regex)then|else)' (è possibile usarle anche nella loro forma negata).
Commenti
E' possibile inserire commenti nella regex con '(?#commento)'. Un'altra alternativa è abilitare la modalità "free-spacing" con cui l'engine ignora gli spazi (su cui, se richiesti, occorre effettuare escape '\ ') e qualsiasi eventuale carattere che segue il simbolo '#' (fino al termina della singola linea). La modalità "free-spacing" non altera il comportamento dentro una classe di caratteri, pertanto eventuali spazi o # verrano considerati con il solito significato.
Regole per l'escaping
Occorre effettuare l'escaping (attraverso l'inserimento di '\' prima del carattere sui cui si effettua l'escape) su '$numero', '\numero', '${' e '\'. E' necessario effettuare l'escape su ogni carattere che abbia un significato non letterale di default.
Saluti.
• Nessun commento •
Inserisci un commento • Inserito il 31 luglio 2009 •
PHP 5.3 & Xdebug & APC install script per Dreamhost
Ecco a voi uno script per installare:• PHP 5.3.0
• Xdebug 2.0.5
• APC 3.1.2
su Dreamhost (ma in realtà può essere facilmente adattato ad altre situazioni).
Lo script è in bash ed è stato originariamente preso dal wiki di DH ma ha subito molte aggiunte per addattarlo ai miei scopi. A differenza dello script originale ho preferito, fin dove possibile, appoggiarmi a librerie già presenti sul sistema, senza imbarcarmi in dispendiose ed ulteriori compilazioni. Ho tentato di preservare tutte le feature presenti nel PHP di base di DH, l'unica rinuncia è stata Kerberos (ho tentato in tutti i modi, ma il configure proprio non le voleva vedere le sue librerie sotto /usr/lib/) che, in ogni caso, è raramente sfruttato con PHP (ma magari mi sbaglio).
In sintesi conclusiva ecco a voi lo script (è necessario personalizzare almeno la variabile DOMAIN):
#!/bin/sh
# Script updated 2009-07-24 by ercoppa (ercoppa.org) to convert this script for PHP 5.3 (with all features of dreamhost,
# except kerberos) with Xdebug and APC
#
# Script updated 2009-05-24 by ksmoe to correct copying of correct PHP cgi file (php-cgi instead of php)
# Script updated 2006-12-25 by Carl McDade (hiveminds.co.uk) to allow memory limit and freetype
#
# Script updated 2007-11-24 by Andrew (ajmconsulting.net) to allow 3rd wget line to pass
# LIBMCRYPT version information (was set as static download file name previously.)
#
# Script updated 2009-4-25 by Daniel (whathuhstudios.com) for latest source versions
#
# Save the code to a file as *.sh
# Abort on any errors
#
set -e
# The domain in which to install the PHP CGI script.
export DOMAIN="librecode.com"
# Where do you want all this stuff built? I'd recommend picking a local
# filesystem.
# ***Don't pick a directory that already exists!*** We clean up after
# ourselves at the end!
SRCDIR=${HOME}/source
# And where should it be installed?
INSTALLDIR=${HOME}/php5
# Set DISTDIR to somewhere persistent, if you plan to muck around with this
# script and run it several times!
DISTDIR=${HOME}/dist
# Pre-download clean up!!!!
rm -rf $SRCDIR
# Update version information here.
PHP5="php-5.3.0"
CURL="curl-7.19.5"
XDEBUG="xdebug-2.0.5"
AUTOCONF="autoconf-2.63"
CCLIENT="imap-2004g"
CCLIENT_DIR="imap-2004g"
OPENSSL="openssl-0.9.8k"
OPENSSL_DIR="openssl-0.9.8k"
LIBMCRYPT="libmcrypt-2.5.8"
APC="APC-3.1.2"
# What PHP features do you want enabled?
PHPFEATURES="--prefix=${INSTALLDIR} \
--with-config-file-path=${INSTALLDIR}/etc/php5/${DOMAIN} \
--with-config-file-scan-dir=${INSTALLDIR}/etc/php5/${DOMAIN} \
--enable-fastcgi \
--bindir=$INSTALLDIR/bin \
--enable-force-cgi-redirect \
--with-xml \
--with-freetype-dir=/usr \
--with-mhash=/usr \
--with-zlib-dir=/usr \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-curl=${INSTALLDIR} \
--with-gd \
--enable-gd-native-ttf \
--enable-memory-limit \
--enable-ftp \
--enable-exif \
--enable-sockets \
--enable-wddx \
--enable-sqlite-utf8 \
--enable-calendar \
--enable-mbstring \
--enable-mbregex \
--enable-bcmath \
--with-mysql=/usr \
--with-mysqli \
--without-pear \
--with-gettext \
--with-pdo-mysql \
--with-openssl=${INSTALLDIR} \
--with-imap=${INSTALLDIR} \
--with-xsl \
--with-ttf=/usr \
--with-xslt \
--with-xslt-sablot=/usr \
--with-dom-xslt=/usr \
--with-mcrypt=${INSTALLDIR} \
--with-imap-ssl=/usr"
# ---- end of user-editable bits. Hopefully! ----
# Push the install dir's bin directory into the path
export PATH=${INSTALLDIR}/bin:$PATH
# set up directories
mkdir -p ${SRCDIR}
mkdir -p ${INSTALLDIR}
if [ ! -f ${DISTDIR} ]
then
mkdir -p ${DISTDIR}
fi
cd ${DISTDIR}
# Get all the required packages
if [ ! -f ${DISTDIR}/${PHP5}.tar.gz ]
then
wget -c http://it.php.net/get/${PHP5}.tar.gz/from/ch.php.net/mirror
fi
if [ ! -f ${DISTDIR}/${CURL}.tar.gz ]
then
wget -c http://curl.haxx.se/download/${CURL}.tar.gz
fi
if [ ! -f ${DISTDIR}/${AUTOCONF}.tar.gz ]
then
wget -c http://ftp.gnu.org/gnu/autoconf/${AUTOCONF}.tar.gz
fi
if [ ! -f ${DISTDIR}/${XDEBUG}.tgz ]
then
wget -c http://xdebug.org/files/${XDEBUG}.tgz
fi
if [ ! -f ${DISTDIR}/${CCLIENT}.tar.Z ]
then
wget -c ftp://ftp.cac.washington.edu/imap/old/${CCLIENT}.tar.Z
fi
if [ ! -f ${DISTDIR}/${OPENSSL}.tar.gz ]
then
wget -c http://www.openssl.org/source/${OPENSSL}.tar.gz
fi
if [ ! -f ${DISTDIR}/${LIBMCRYPT}.tar.gz ]
then
wget -c http://easynews.dl.sourceforge.net/sourceforge/mcrypt/${LIBMCRYPT}.tar.gz
fi
if [ ! -f ${DISTDIR}/${APC}.tgz ]
then
wget -c http://pecl.php.net/get/${APC}.tgz
fi
echo ---------- Unpacking downloaded archives. This process may take several minutes! ----------
cd ${SRCDIR}
# Unpack them all
echo Extracting ${PHP5}...
tar xzf ${DISTDIR}/${PHP5}.tar.gz
echo Done.
echo Extracting ${CURL}...
tar xzf ${DISTDIR}/${CURL}.tar.gz
echo Done.
echo Extracting ${XDEBUG}...
tar xzf ${DISTDIR}/${XDEBUG}.tgz
echo Done.
echo Extracting ${AUTOCONF}...
tar xzf ${DISTDIR}/${AUTOCONF}.tar.gz
echo Done.
echo Extracting ${CCLIENT}...
uncompress -cd ${DISTDIR}/${CCLIENT}.tar.Z |tar x
echo Done.
echo Extracting ${OPENSSL}...
uncompress -cd ${DISTDIR}/${OPENSSL}.tar.gz |tar x
echo Done.
echo Extracting ${LIBMCRYPT}...
tar xzf ${DISTDIR}/${LIBMCRYPT}.tar.gz
echo Done.
echo Extracting ${APC}...
tar xzf ${DISTDIR}/${APC}.tgz
echo Done.
# Build them in the required order to satisfy dependencies
#cURL
echo ###################
echo Compile CURL
echo ###################
cd ${SRCDIR}/${CURL}
./configure --enable-ipv6 --enable-cookies \
--enable-crypto-auth --prefix=${INSTALLDIR}
# make clean
make
make install
#CCLIENT
echo ###################
echo Compile CCLIENT
echo ###################
cd ${SRCDIR}/${CCLIENT_DIR}
make ldb
# Install targets are for wusses!
cp c-client/c-client.a ${INSTALLDIR}/lib/libc-client.a
cp c-client/*.h ${INSTALLDIR}/include
#OPENSSL
echo ###################
echo Compile OPENSSL
echo ###################
# openssl
cd ${SRCDIR}/${OPENSSL_DIR}
./config --prefix=${INSTALLDIR}
make
make install
#MCRYPT
echo ###################
echo Compile MCRYPT
echo ###################
cd ${SRCDIR}/${LIBMCRYPT}
./configure --disable-posix-threads --prefix=${INSTALLDIR}
# make clean
make
make install
#PHP 5
echo ###################
echo Compile PHP
echo ###################
cd ${SRCDIR}/${PHP5}
./configure ${PHPFEATURES}
# make clean
make
make install
# Copy a basic configuration for PHP
mkdir -p ${INSTALLDIR}/etc/php5/${DOMAIN}
cp ${SRCDIR}/${PHP5}/php.ini-production ${INSTALLDIR}/etc/php5/${DOMAIN}/php.ini
#AUTOCONF
echo ###################
echo Compile AUTOCONF
echo ###################
cd ${SRCDIR}/${AUTOCONF}
./configure --prefix=${INSTALLDIR}
# make clean
make
make install
# XDEBUG
echo ###################
echo Compile XDEBUG
echo ###################
cd ${SRCDIR}/${XDEBUG}
export PHP_AUTOHEADER=${INSTALLDIR}/bin/autoheader
export PHP_AUTOCONF=${INSTALLDIR}/bin/autoconf
echo $PHP_AUTOHEADER
echo $PHP_AUTOCONF
${INSTALLDIR}/bin/phpize
./configure --enable-xdebug --with-php-config=${INSTALLDIR}/bin/php-config --prefix=${INSTALLDIR}
# make clean
make
mkdir -p ${INSTALLDIR}/extensions
cp modules/xdebug.so ${INSTALLDIR}/extensions
echo "zend_extension=${INSTALLDIR}/extensions/xdebug.so" >> ${INSTALLDIR}/etc/php5/${DOMAIN}/xdebug.ini
# APC
echo ###################
echo Compile APC
echo ###################
cd ${SRCDIR}/${APC}
${INSTALLDIR}/bin/phpize
./configure --enable-apc --enable-apc-mmap --with-php-config=${INSTALLDIR}/bin/php-config --prefix=${INSTALLDIR}
# make clean
make
cp modules/apc.so ${INSTALLDIR}/extensions
echo "extension=${INSTALLDIR}/extensions/apc.so" >> ${INSTALLDIR}/etc/php5/${DOMAIN}/apc.ini
# Copy PHP CGI
mkdir -p ${HOME}/${DOMAIN}/cgi-bin
chmod 0755 ${HOME}/${DOMAIN}/cgi-bin
cp ${INSTALLDIR}/bin/php-cgi ${HOME}/${DOMAIN}/cgi-bin/php.cgi
rm -rf $SRCDIR $DISTDIR
# Create .htaccess
if [ -f ${HOME}/${DOMAIN}/.htaccess ]
then
echo #
echo '#####################################################################'
echo ' Your domain already has a .htaccess, it is ranamed .htaccess_old '
echo ' --> PLEASE FIX THIS PROBLEM <-- '
echo '#####################################################################'
echo #
mv ${HOME}/${DOMAIN}/.htaccess ${HOME}/${DOMAIN}/.htaccess_old
fi
echo 'Options +ExecCGI' >> ${HOME}/${DOMAIN}/.htaccess
echo 'AddHandler php-cgi .php' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Action php-cgi /cgi-bin/php.cgi' >> ${HOME}/${DOMAIN}/.htaccess
echo '' >> ${HOME}/${DOMAIN}/.htaccess
echo '<FilesMatch "^php5?\.(ini|cgi)$">' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Order Deny,Allow' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Deny from All' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Allow from env=REDIRECT_STATUS' >> ${HOME}/${DOMAIN}/.htaccess
echo '</FilesMatch>' >> ${HOME}/${DOMAIN}/.htaccess
echo ---------- INSTALL COMPLETE! ----------
echo
echo 'Configuration files:'
echo "1) General PHP -> ${INSTALLDIR}/etc/php5/${DOMAIN}/php.ini"
echo "2) Xdebug conf -> ${INSTALLDIR}/etc/php5/${DOMAIN}/xdebug.ini"
echo "3) APC conf -> ${INSTALLDIR}/etc/php5/${DOMAIN}/apc.ini"
echo
echo 'You have to modify these files in order to enable Xdebug or APC features.'
exit 0
# Script updated 2009-07-24 by ercoppa (ercoppa.org) to convert this script for PHP 5.3 (with all features of dreamhost,
# except kerberos) with Xdebug and APC
#
# Script updated 2009-05-24 by ksmoe to correct copying of correct PHP cgi file (php-cgi instead of php)
# Script updated 2006-12-25 by Carl McDade (hiveminds.co.uk) to allow memory limit and freetype
#
# Script updated 2007-11-24 by Andrew (ajmconsulting.net) to allow 3rd wget line to pass
# LIBMCRYPT version information (was set as static download file name previously.)
#
# Script updated 2009-4-25 by Daniel (whathuhstudios.com) for latest source versions
#
# Save the code to a file as *.sh
# Abort on any errors
#
set -e
# The domain in which to install the PHP CGI script.
export DOMAIN="librecode.com"
# Where do you want all this stuff built? I'd recommend picking a local
# filesystem.
# ***Don't pick a directory that already exists!*** We clean up after
# ourselves at the end!
SRCDIR=${HOME}/source
# And where should it be installed?
INSTALLDIR=${HOME}/php5
# Set DISTDIR to somewhere persistent, if you plan to muck around with this
# script and run it several times!
DISTDIR=${HOME}/dist
# Pre-download clean up!!!!
rm -rf $SRCDIR
# Update version information here.
PHP5="php-5.3.0"
CURL="curl-7.19.5"
XDEBUG="xdebug-2.0.5"
AUTOCONF="autoconf-2.63"
CCLIENT="imap-2004g"
CCLIENT_DIR="imap-2004g"
OPENSSL="openssl-0.9.8k"
OPENSSL_DIR="openssl-0.9.8k"
LIBMCRYPT="libmcrypt-2.5.8"
APC="APC-3.1.2"
# What PHP features do you want enabled?
PHPFEATURES="--prefix=${INSTALLDIR} \
--with-config-file-path=${INSTALLDIR}/etc/php5/${DOMAIN} \
--with-config-file-scan-dir=${INSTALLDIR}/etc/php5/${DOMAIN} \
--enable-fastcgi \
--bindir=$INSTALLDIR/bin \
--enable-force-cgi-redirect \
--with-xml \
--with-freetype-dir=/usr \
--with-mhash=/usr \
--with-zlib-dir=/usr \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-curl=${INSTALLDIR} \
--with-gd \
--enable-gd-native-ttf \
--enable-memory-limit \
--enable-ftp \
--enable-exif \
--enable-sockets \
--enable-wddx \
--enable-sqlite-utf8 \
--enable-calendar \
--enable-mbstring \
--enable-mbregex \
--enable-bcmath \
--with-mysql=/usr \
--with-mysqli \
--without-pear \
--with-gettext \
--with-pdo-mysql \
--with-openssl=${INSTALLDIR} \
--with-imap=${INSTALLDIR} \
--with-xsl \
--with-ttf=/usr \
--with-xslt \
--with-xslt-sablot=/usr \
--with-dom-xslt=/usr \
--with-mcrypt=${INSTALLDIR} \
--with-imap-ssl=/usr"
# ---- end of user-editable bits. Hopefully! ----
# Push the install dir's bin directory into the path
export PATH=${INSTALLDIR}/bin:$PATH
# set up directories
mkdir -p ${SRCDIR}
mkdir -p ${INSTALLDIR}
if [ ! -f ${DISTDIR} ]
then
mkdir -p ${DISTDIR}
fi
cd ${DISTDIR}
# Get all the required packages
if [ ! -f ${DISTDIR}/${PHP5}.tar.gz ]
then
wget -c http://it.php.net/get/${PHP5}.tar.gz/from/ch.php.net/mirror
fi
if [ ! -f ${DISTDIR}/${CURL}.tar.gz ]
then
wget -c http://curl.haxx.se/download/${CURL}.tar.gz
fi
if [ ! -f ${DISTDIR}/${AUTOCONF}.tar.gz ]
then
wget -c http://ftp.gnu.org/gnu/autoconf/${AUTOCONF}.tar.gz
fi
if [ ! -f ${DISTDIR}/${XDEBUG}.tgz ]
then
wget -c http://xdebug.org/files/${XDEBUG}.tgz
fi
if [ ! -f ${DISTDIR}/${CCLIENT}.tar.Z ]
then
wget -c ftp://ftp.cac.washington.edu/imap/old/${CCLIENT}.tar.Z
fi
if [ ! -f ${DISTDIR}/${OPENSSL}.tar.gz ]
then
wget -c http://www.openssl.org/source/${OPENSSL}.tar.gz
fi
if [ ! -f ${DISTDIR}/${LIBMCRYPT}.tar.gz ]
then
wget -c http://easynews.dl.sourceforge.net/sourceforge/mcrypt/${LIBMCRYPT}.tar.gz
fi
if [ ! -f ${DISTDIR}/${APC}.tgz ]
then
wget -c http://pecl.php.net/get/${APC}.tgz
fi
echo ---------- Unpacking downloaded archives. This process may take several minutes! ----------
cd ${SRCDIR}
# Unpack them all
echo Extracting ${PHP5}...
tar xzf ${DISTDIR}/${PHP5}.tar.gz
echo Done.
echo Extracting ${CURL}...
tar xzf ${DISTDIR}/${CURL}.tar.gz
echo Done.
echo Extracting ${XDEBUG}...
tar xzf ${DISTDIR}/${XDEBUG}.tgz
echo Done.
echo Extracting ${AUTOCONF}...
tar xzf ${DISTDIR}/${AUTOCONF}.tar.gz
echo Done.
echo Extracting ${CCLIENT}...
uncompress -cd ${DISTDIR}/${CCLIENT}.tar.Z |tar x
echo Done.
echo Extracting ${OPENSSL}...
uncompress -cd ${DISTDIR}/${OPENSSL}.tar.gz |tar x
echo Done.
echo Extracting ${LIBMCRYPT}...
tar xzf ${DISTDIR}/${LIBMCRYPT}.tar.gz
echo Done.
echo Extracting ${APC}...
tar xzf ${DISTDIR}/${APC}.tgz
echo Done.
# Build them in the required order to satisfy dependencies
#cURL
echo ###################
echo Compile CURL
echo ###################
cd ${SRCDIR}/${CURL}
./configure --enable-ipv6 --enable-cookies \
--enable-crypto-auth --prefix=${INSTALLDIR}
# make clean
make
make install
#CCLIENT
echo ###################
echo Compile CCLIENT
echo ###################
cd ${SRCDIR}/${CCLIENT_DIR}
make ldb
# Install targets are for wusses!
cp c-client/c-client.a ${INSTALLDIR}/lib/libc-client.a
cp c-client/*.h ${INSTALLDIR}/include
#OPENSSL
echo ###################
echo Compile OPENSSL
echo ###################
# openssl
cd ${SRCDIR}/${OPENSSL_DIR}
./config --prefix=${INSTALLDIR}
make
make install
#MCRYPT
echo ###################
echo Compile MCRYPT
echo ###################
cd ${SRCDIR}/${LIBMCRYPT}
./configure --disable-posix-threads --prefix=${INSTALLDIR}
# make clean
make
make install
#PHP 5
echo ###################
echo Compile PHP
echo ###################
cd ${SRCDIR}/${PHP5}
./configure ${PHPFEATURES}
# make clean
make
make install
# Copy a basic configuration for PHP
mkdir -p ${INSTALLDIR}/etc/php5/${DOMAIN}
cp ${SRCDIR}/${PHP5}/php.ini-production ${INSTALLDIR}/etc/php5/${DOMAIN}/php.ini
#AUTOCONF
echo ###################
echo Compile AUTOCONF
echo ###################
cd ${SRCDIR}/${AUTOCONF}
./configure --prefix=${INSTALLDIR}
# make clean
make
make install
# XDEBUG
echo ###################
echo Compile XDEBUG
echo ###################
cd ${SRCDIR}/${XDEBUG}
export PHP_AUTOHEADER=${INSTALLDIR}/bin/autoheader
export PHP_AUTOCONF=${INSTALLDIR}/bin/autoconf
echo $PHP_AUTOHEADER
echo $PHP_AUTOCONF
${INSTALLDIR}/bin/phpize
./configure --enable-xdebug --with-php-config=${INSTALLDIR}/bin/php-config --prefix=${INSTALLDIR}
# make clean
make
mkdir -p ${INSTALLDIR}/extensions
cp modules/xdebug.so ${INSTALLDIR}/extensions
echo "zend_extension=${INSTALLDIR}/extensions/xdebug.so" >> ${INSTALLDIR}/etc/php5/${DOMAIN}/xdebug.ini
# APC
echo ###################
echo Compile APC
echo ###################
cd ${SRCDIR}/${APC}
${INSTALLDIR}/bin/phpize
./configure --enable-apc --enable-apc-mmap --with-php-config=${INSTALLDIR}/bin/php-config --prefix=${INSTALLDIR}
# make clean
make
cp modules/apc.so ${INSTALLDIR}/extensions
echo "extension=${INSTALLDIR}/extensions/apc.so" >> ${INSTALLDIR}/etc/php5/${DOMAIN}/apc.ini
# Copy PHP CGI
mkdir -p ${HOME}/${DOMAIN}/cgi-bin
chmod 0755 ${HOME}/${DOMAIN}/cgi-bin
cp ${INSTALLDIR}/bin/php-cgi ${HOME}/${DOMAIN}/cgi-bin/php.cgi
rm -rf $SRCDIR $DISTDIR
# Create .htaccess
if [ -f ${HOME}/${DOMAIN}/.htaccess ]
then
echo #
echo '#####################################################################'
echo ' Your domain already has a .htaccess, it is ranamed .htaccess_old '
echo ' --> PLEASE FIX THIS PROBLEM <-- '
echo '#####################################################################'
echo #
mv ${HOME}/${DOMAIN}/.htaccess ${HOME}/${DOMAIN}/.htaccess_old
fi
echo 'Options +ExecCGI' >> ${HOME}/${DOMAIN}/.htaccess
echo 'AddHandler php-cgi .php' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Action php-cgi /cgi-bin/php.cgi' >> ${HOME}/${DOMAIN}/.htaccess
echo '' >> ${HOME}/${DOMAIN}/.htaccess
echo '<FilesMatch "^php5?\.(ini|cgi)$">' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Order Deny,Allow' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Deny from All' >> ${HOME}/${DOMAIN}/.htaccess
echo 'Allow from env=REDIRECT_STATUS' >> ${HOME}/${DOMAIN}/.htaccess
echo '</FilesMatch>' >> ${HOME}/${DOMAIN}/.htaccess
echo ---------- INSTALL COMPLETE! ----------
echo
echo 'Configuration files:'
echo "1) General PHP -> ${INSTALLDIR}/etc/php5/${DOMAIN}/php.ini"
echo "2) Xdebug conf -> ${INSTALLDIR}/etc/php5/${DOMAIN}/xdebug.ini"
echo "3) APC conf -> ${INSTALLDIR}/etc/php5/${DOMAIN}/apc.ini"
echo
echo 'You have to modify these files in order to enable Xdebug or APC features.'
exit 0
P.s. lo script è disponibile anche qui ed il risultato dello script è visibile qui (banale phpinfo()).
Saluti.
• Visualizza i commenti (1) • Inserisci un commento • Inserito il 24 luglio 2009 •
Calcolo media ponderata per Ingegneria Informatica Roma La Sapienza
Oggi non avendo troppi pensieri per la testa, ho fatto uno script per calcolare la media ponderata sui CFU, eccoli (in base all'ordinamento):• primo anno nuovo ordinamento (esami da 5 CFU), secondo e terzo anno nuovissmo ordinamento
• primo anno nuovo ordinamento (esami da 5 CFU), secondo e terzo anno nuovissimo ordinamento ma con qualche esame del primo anno recuperato in base al nuovissimo ordinamento
• nuovissimo ordinamento
I voti, se opportunamente scelto, vengono salvati in un cookie per il successivo calcolo della media.
Saluti.
• Visualizza i commenti (32) • Inserisci un commento • Inserito il 11 luglio 2009 •