La secuencia de comandos por lotes para reemplazar las tags abreviadas de PHP con <? Php

Tengo una gran colección de archivos php escritos a lo largo de los años y necesito reemplazar correctamente todas las tags abiertas cortas en tags abiertas explícitas adecuadas.

change "<?" into "<?php" 

Creo que esta expresión regular los seleccionará correctamente:

 <\?(\s|\n|\t|[^a-zA-Z]) 

que se ocupa de casos como

 <?// <?/* 

pero no estoy seguro de cómo procesar un árbol de carpetas completo y detectar la extensión de archivo .php, aplicar la expresión regular y guardar el archivo después de que se haya modificado.

Tengo la sensación de que esto puede ser bastante sencillo si dominas las herramientas adecuadas. (Hay un truco interesante en el manual de sed: 4.3 Ejemplo / Cambiar el nombre de los archivos a minúsculas ).

Puede ser que esté equivocado.
O tal vez esto podría ser un oneliner?

no use expresiones regulares para analizar lenguajes formales; siempre encontrará páramos que no anticipó. me gusta:

  now what?  

es más seguro usar un procesador que conozca la estructura del lenguaje. para html, eso sería un procesador xml; para php, la extensión tokenizer incorporada. tiene el T_OPEN_TAG analizador T_OPEN_TAG , que coincide con , o <% , y T_OPEN_TAG_WITH_ECHO , que coincide con o <%= . para reemplazar todas las tags abiertas cortas, encontrará todos estos tokens y reemplazará T_OPEN_TAG con y T_OPEN_TAG_WITH_ECHO con .

la implementación se deja como un ejercicio para el lector :)

EDITOR 1 : el maestro de ceremonias fue tan amable de proporcionar uno .

EDIT 2 : en sistemas con short_open_tag desactivado en php.ini , , <% y no serán reconocidos por un script de reemplazo. para que la secuencia de comandos funcione en dichos sistemas, habilite short_open_tag mediante la opción de línea de comando:

 php -d short_open_tag=On short_open_tag_replacement_script.php 

ps la página man para token_get_all () y googleing para las combinaciones de tokenizer , token_get_all y los nombres del token del analizador pueden ayudar.

pps ver también Regex para analizar los contenidos de definir (), ¿es posible? aquí en SO

Si está utilizando la opción tokenizer, esto podría ser útil:

 $content = file_get_contents($file); $tokens = token_get_all($content); $output = ''; foreach($tokens as $token) { if(is_array($token)) { list($index, $code, $line) = $token; switch($index) { case T_OPEN_TAG_WITH_ECHO: $output .= ' 

Tenga en cuenta que el tokenizador no tokenizará las tags cortas si las tags cortas no están habilitadas. Es decir, no puede ejecutar este código en el sistema donde las tags cortas no funcionan. Debe ejecutarlo en otro lugar para convertir el código.

Esta es una utilidad que escribí que convierte fuente PHP que contiene tags cortas abiertas y las reemplaza con tags largas.

es decir, convierte un código como este:

    

A esto

    

La opción –skip-echo-tags provocará que omita tags Y solo reemplace tags.

Está escrito como un script PHP-CLI y necesita que el archivo CLI php.ini se configure para permitir tags abreviadas cortas. Esa es la configuración predeterminada para PHP 5.3.0 y versiones anteriores, pero puede no ser siempre así. (El script simplemente no cambiará nada si la configuración no está habilitada).

Mi respuesta anterior, simplemente sobrescribí con sed, no funciona, sed es demasiado débil para este tipo de cosas IMO.

Así que he creado un script perl que debería funcionar, es muy fácil de editar por el usuario.

 #!/usr/bin/perl use strict; use warnings; use File::Find::Rule; use Carp; my @files = File::Find::Rule->file()->name('*.php')->in('/tmp/foo/bar'); for my $file (@files) { rename $file, $file . '.orig'; open my $output, '>', $file or Carp::croak("Write Error with $file $! [email protected] "); open my $input, '<', $file . '.orig' or Carp::croak("Read error with $file.orig $! [email protected]"); while ( my $line = <$input> ) { # Replace  

Pero tenga en cuenta que no he probado esto en ningún código real, por lo que podría ir "Bang".

Le recomendaría que revisara su código (espere, ya está revisado, ¿verdad? ... ¿verdad?) Y ejecute su suite de pruebas (¡No me diga que no tiene pruebas!) En el código modificado, porque puede Es seguro que está haciendo lo correcto sin un analizador FSM de pleno derecho.

Voy a simplificar su expresión regular a los efectos de esto en lo que puede funcionar mejor, pero puedo estar equivocado ya que no lo he probado en ningún código real.

Digamos que estás sentado en el directorio base de tu código, puedes comenzar con:

 find . -iname "*.php" -print0 

Eso te proporcionará todos los archivos .php, separados por caracteres NULL, que es necesario en caso de que alguno de ellos tenga espacios.

 find . -iname "*.php" -print0 | xargs -0 -I{} sed -n 's/\(<\?\)\([^a-zA-Z]\)/\1php\2/gp' '{}' 

Esto debería llevarte la mayor parte del camino hasta allí. Encontrará todos los archivos, luego, para cada uno, ejecutar sed para reemplazar el código. Sin embargo, sin la etiqueta -i (utilizada a continuación), esto no afectará a sus archivos, simplemente enviará su código a su terminal. El -n suprime la salida normal, y la p después de la parte de la expresión regular le dice que imprima solo las líneas que cambiaron.

De acuerdo, si los resultados parecen correctos, entonces da el gran paso, que es reemplazar los archivos en el lugar. ¡Definitivamente debería realizar una copia de seguridad de todos sus archivos antes de intentar esto!

 find . -iname "*.php" -print0 | xargs -0 -I{} sed -i 's/\(<\?\)\([^a-zA-Z]\)/\1php\2/g' '{}' 

Eso debería hacer el trabajo. Lamentablemente, no tengo ningún archivo PHP que use esa syntax, por lo que estás solo para resolverlo desde aquí, pero espero que la mecánica de hacer las cosas sea un poco más clara ahora:

  1. Coge todos los archivos con "buscar"
  2. Envíe esa lista de archivos a "xargs" (que hace algún comando en los archivos uno a la vez)
  3. ¡Usa "sed" y la syntax 's / to-change / changed /' para poner tu magia regex a trabajar!

Esa es mi versión de RegExp:

 <\?(?!(php|=|xml))(\s|\t|\n) 

Usé la secuencia de comandos de danorton en casi 2000 archivos y funcionó como un encanto

Puse su script en un archivo llamado “fixtags.php” y usé el siguiente linux 1 para resolver el problema:

 find . -iname "*.php" | xargs php fixtags.php --overwrite 

el único problema que tuve fue cuando encontró un archivo que tenía cero bytes de tamaño.

El problema ha sido resuelto como un fijador en la herramienta php-cs-fixer que se puede instalar fácilmente y que se prueba y se mantiene.

La reparación es fácil:

 $ php-cs-fixer fix --fixers=short_tag --diff --dry-run  

Simplemente reemplace con la ruta al directorio o archivo que desea cambiar. El comando dado es revisar primero ( --dry-run y --diff parámetros).

La instalación es tan fácil como

 $ composer global require friendsofphp/php-cs-fixer 

si tiene el compositor instalado con el directorio global bin de compositor en su ruta (recomendado).

Tuve que pasar por esto antes y me pareció mejor hacerlo en etapas. Una mala secuencia de comandos que intenta atraparlo puede estropear MUCHOS archivos.

Usé Coda (o cualquier otro editor web) para hacer un simple descubrimiento y reemplazarlo en cadenas muy específicas.

Por ejemplo, comenzando con ”

Puede parecer un poco más tedioso, pero estaba seguro de que algo no se estaba arruinando en un lugar que yo no sabía. Volver es un verdadero dolor.

Es típico que las páginas XML / XHTML incluyan el siguiente código:

 '; ?> 

Por supuesto, eso no debe cambiar ni a:

 '; ?> 

ni:

 '; ?> 

Desafortunadamente, las soluciones automáticas pueden no funcionar. Mi recomendación:

1) Use grep para encontrar todas las tags cortas:

 grep -rn " 

2) Revise cada archivo y línea y corríjalo manualmente

Entiendo que esta podría no ser una solución viable si tienes un gran proyecto, pero para mí funcionó bien.

Aquí hay un perl de una sola línea:

 perl -pi -w -e 's/\<\?/\<\?php/g;' *php 

Utilice el control de versión para escenificar y decida mantener los cambios o no.