A continuación se muestra un extracto de un script que escribí en PHP, pero que contiene un comando del sistema que se ejecuta en formato bash
. Ahora, la razón de esto es porque me permite usar la awk
función que es ideal en el escenario que se me ha presentado. Estoy intentando obtener el cuarto o quinto elemento de una cadena (almacenado en $line
), con el que luego planeo trabajar. Sin embargo, cada vez que lo ejecuto con el siguiente código me aparece el siguiente error:
PHP Parse error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16
La línea 16 es mi primer comando del sistema:
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
Sin embargo, debido a mi falta de experiencia tanto con PHP como con la función del sistema, no estoy seguro de qué está causando exactamente mi problema. ¿Alguien puede arrojar algo de luz sobre esto? Intenté investigar el problema, sin embargo, el error es bastante genérico y mi situación es bastante única, ya que muchos de los awk
problemas en la web son parte de un escenario en el que la persona lo ejecuta desde la CLI en lugar de un script PHP.
Aquí hay un ejemplo de qué datos estarían en la $line
variable:
GiX/X down down CUSTOMER: NX/XXXXXXX : 1Mbps - Offshore SLA
Código a continuación:
$skipFirstLine = 1;
foreach($outputFile as &$line)
{
if($skipFirstLine == 0)
{
if(strpos($line, 'admin down'))
{
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
}
else
{
system("echo \"$line\" | awk '{$1=$2=$3=""; print $0}'");
}
}
else
{
$skipFirstLine = 0;
}
}
Respuesta1
Tienes este fragmento en un script PHP:
"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"
Hay muchos problemas con esto:
- Estas son dos cadenas literales yuxtapuestas
"echo \"$line\" | awk '{$1=$2=$3=$4="
y"; print $0}'"
. Esta no es una sintaxis PHP válida. Debes proteger estas dos comillas dobles con una barra invertida. $
en una cadena PHP entre comillas dobles se expande mediante PHP. Tienes que\$
evitar esto.- Su
line
variable es una variable PHP que contiene una cadena. Pero lo estás usando dentro de un script de shell, donde el shell lo analizará. Con lo que ha escrito, suponga que el contenido de esta variable es$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down
: entonces el servidor entregará felizmente un volcado de la base de datos (este comando exacto puede funcionar o no dependiendo de cómo se use el script PHP, pero espero que entienda la idea). ).
Para resolver el último problema, que es el más complejo, puedes evitar problemas de cotización pasando la variable a través del entorno. El shell ve las variables de entorno como variables de shell.
putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");
Como alternativa, utilice comillas simples en PHP, que requieren entrecomillas únicamente de \
y '
.
system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');
Si desea pasar una cadena a un script de shell, debe citarla correctamente para el shell. La forma más sencilla de hacerlo es convertirlo en un literal entre comillas simples; esto requiere transformar las comillas simples dentro de la cadena.
$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');
Pero¿Por qué estás llamando a un script de shell en primer lugar?? PHP tiene todo lo que necesitas para realizar manipulaciones de texto simples como estas. Llamar a un script de Shell no solo es extraño, sino que también es extremadamente frágil (como muestra esta respuesta); seguramente lo entenderás mal, así que no lo hagas.
print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', ' ', $line));
(Tenga en cuenta que es posible que no haya escrito exactamente lo que quería, porque 1. su código awk es extraño (¿por qué conserva algunos espacios al principio?) y 2. No sé PHP).
No ponga este código en producción hasta que comprenda lo que está haciendo. Una vez que se corrigen los errores de sintaxis más apremiantes, tendrá un código plagado de agujeros de seguridad (permite $line
que sea un comando de shell arbitrario; no hay nada más fácil de explotar que eso). No permita que este código se ejecute fuera de su máquina de prueba (con suerte, protegida por firewall) hasta que haya pasado por una revisión de seguridad exhaustiva.
Respuesta2
Intente utilizar comillas simples en lugar de comillas dobles.
system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\'');
Las comillas simples mostrarán las cosas casi siempre "tal cual". Más detalles puedes encontraren documentación oficial