Unten sehen Sie einen Auszug aus einem Skript, das ich in PHP geschrieben habe, das aber einen Systembefehl enthält, der in ausgeführt wird bash
. Der Grund dafür ist, dass ich dadurch die Funktion verwenden kann awk
, die für das mir vorliegende Szenario ideal ist. Ich versuche, das vierte oder fünfte Element einer Zeichenfolge (gespeichert in $line
) abzurufen, mit der ich dann arbeiten möchte. Wenn ich es jedoch mit dem folgenden Code ausführe, wird mir der folgende Fehler angezeigt:
PHP Parse error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16
Zeile 16 ist mein erster Systembefehl:
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
Aufgrund meiner mangelnden Erfahrung mit PHP und der Systemfunktion bin ich mir jedoch nicht sicher, was genau mein Problem verursacht. Kann jemand möglicherweise Licht in die Sache bringen? Ich habe versucht, das Problem zu untersuchen, der Fehler ist jedoch recht allgemein und meine Situation ist recht einzigartig, da viele der awk
Probleme im Web Teil eines Szenarios sind, in dem die Person es über die CLI und nicht über ein PHP-Skript ausführt.
$line
Hier ist ein Beispiel dafür, welche Daten in der Variable enthalten wären :
GiX/X down down CUSTOMER: NX/XXXXXXX : 1Mbps - Offshore SLA
Code unten:
$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;
}
}
Antwort1
Sie haben diesen Snippet in einem PHP-Skript:
"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"
Dies bringt viele Probleme mit sich:
- Dies sind zwei nebeneinander stehende Stringliterale,
"echo \"$line\" | awk '{$1=$2=$3=$4="
und"; print $0}'"
. Dies ist keine gültige PHP-Syntax. Sie müssen diese beiden Anführungszeichen mit einem Backslash schützen. $
in einem PHP-String in doppelten Anführungszeichen wird mit PHP erweitert.\$
Das müssen Sie vermeiden.- Ihre
line
Variable ist eine PHP-Variable, die einen String enthält. Sie verwenden sie jedoch in einem Shell-Skript, wo sie von der Shell analysiert wird. Nehmen wir mit dem, was Sie geschrieben haben, an, dass der Inhalt dieser Variable ist$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down
– dann wird der Server gerne einen Datenbank-Dump bereitstellen (dieser genaue Befehl funktioniert möglicherweise oder nicht, je nachdem, wie das PHP-Skript verwendet wird, aber ich hoffe, Sie verstehen, was ich meine).
Um das letzte und komplexeste Problem zu lösen, können Sie Anführungszeichen vermeiden, indem Sie die Variable über die Umgebung übergeben. Umgebungsvariablen werden von der Shell als Shellvariablen betrachtet.
putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");
Alternativ können Sie in PHP einfache Anführungszeichen verwenden, bei denen nur die Anführungszeichen von \
und erforderlich sind '
.
system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');
Wenn Sie einen String an ein Shell-Skript übergeben möchten, müssen Sie ihn für die Shell richtig in Anführungszeichen setzen. Am einfachsten geht das, indem Sie ihn in ein einfaches Anführungszeichen setzen. Dazu müssen Sie die einfachen Anführungszeichen im String umwandeln.
$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');
Aberwarum rufst du überhaupt ein Shell-Skript auf? PHP bietet alles, was Sie für einfache Textmanipulationen wie diese benötigen. Ein Shell-Skript aufzurufen ist nicht nur seltsam, sondern auch extrem fehleranfällig (wie diese Antwort zeigt); Sie werden es mit Sicherheit falsch machen, also tun Sie es nicht.
print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', ' ', $line));
(Beachten Sie, dass ich möglicherweise nicht genau das geschrieben habe, was Sie wollten, weil 1. Ihr Awk-Code seltsam ist (warum behalten Sie am Anfang ein paar Leerzeichen bei?) und 2. ich kein PHP kenne.)
Setzen Sie diesen Code nicht in die Produktion ein, bis Sie wissen, was Sie tun. Sobald die dringendsten Syntaxfehler behoben sind, haben Sie Code, der voller Sicherheitslücken steckt (Sie lassen es zu, $line
ein beliebiger Shell-Befehl zu sein – einfacher kann man ihn nicht ausnutzen). Lassen Sie diesen Code nicht außerhalb Ihrer (hoffentlich durch eine Firewall geschützten) Testmaschine ausführen, bis er einer gründlichen Sicherheitsüberprüfung unterzogen wurde.
Antwort2
Versuchen Sie, einfache Anführungszeichen anstelle von doppelten Anführungszeichen zu verwenden
system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\'');
Einfache Anführungszeichen zeigen die Dinge fast immer so an, wie sie sind. Weitere Details finden Sie hierin der offiziellen Dokumentation