以下は、PHP で作成したスクリプトからの抜粋ですが、 で実行されるシステム コマンドが含まれていますbash
。その理由は、awk
提示されたシナリオに最適な 関数を使用できるからです。 に格納されている文字列の 4 番目または 5 番目の要素を取得して$line
、それを操作する計画です。ただし、以下のコードで実行すると、常に次のエラーが表示されます。
PHP Parse error: syntax error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in /home/hugh/HughScripts/ParseOutputForFieldsV2.php on line 16
16 行目は最初のシステム コマンドです。
system("echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'");
しかし、PHP とシステム機能の両方に関する専門知識が不足しているため、問題の原因が正確に何なのかわかりません。誰かこの問題の原因を解明してもらえませんか? 問題を調べてみましたが、エラーは非常に一般的で、私の状況は非常に特殊です。Webawk
上の多くの問題は、PHP スクリプトではなく CLI から実行しているシナリオの一部です。
変数に含まれるデータの例を次に示します$line
。
GiX/X down down CUSTOMER: NX/XXXXXXX : 1Mbps - Offshore SLA
以下のコード:
$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;
}
}
答え1
PHP スクリプトに次のスニペットがあります:
"echo \"$line\" | awk '{$1=$2=$3=$4=""; print $0}'"
これには多くの問題があります:
- これらは 2 つの並置された文字列リテラルです
"echo \"$line\" | awk '{$1=$2=$3=$4="
。"; print $0}'"
これは有効な PHP 構文ではありません。これら 2 つの二重引用符をバックスラッシュで保護する必要があります。 $
二重引用符で囲まれた PHP 文字列内の は PHP によって展開されます。\$
これを避ける必要があります。- 変数
line
は文字列を含む PHP 変数です。ただし、シェル スクリプト内で使用しているため、シェルによって解析されます。記述した内容で、この変数の内容が次のとおりであると仮定すると、$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down
サーバーはデータベース ダンプを適切に提供します (このコマンドは、PHP スクリプトの使用方法に応じて機能する場合と機能しない場合があります。ただし、この考え方は理解していただければ幸いです)。
最も複雑な最後の問題を解決するには、変数を環境経由で渡すことで引用符の問題を回避できます。環境変数は、シェルによってシェル変数として認識されます。
putenv("PHP_line=$line");
system("echo \"\$PHP_line\" | awk '{\$1=\$2=\$3=\$4=\"\"; print \$0}'");
あるいは、PHP では、 と のみを引用符で囲む必要がある一重引用符を使用し\
ます'
。
system('echo "$PHP_line" | awk \'{$1=$2=$3=$4=""; print $0}\'');
文字列をシェル スクリプトに渡す場合は、シェル用に適切に引用符で囲む必要があります。これを行う最も簡単な方法は、文字列を一重引用符で囲んだリテラルにすることです。これには、文字列内の一重引用符を変換する必要があります。
$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');
しかしそもそもなぜシェルスクリプトを呼び出すのか? PHP には、このような単純なテキスト操作を実行するために必要なものがすべて揃っています。シェル スクリプトの呼び出しは奇妙なだけでなく、非常に脆弱です (この回答が示すように)。間違える可能性が高いため、実行しないでください。
print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', ' ', $line));
(1. awk コードが奇妙 (なぜ先頭にいくつかのスペースを残しているのですか?)、2. 私は PHP を知らないため、私が書きたかった通りのものが書けなかった可能性があることに注意してください。)
自分が何をしているのか理解するまで、このコードを本番環境に導入しないでください。最も差し迫った構文エラーが修正されると、セキュリティ ホールだらけのコードになります ($line
任意のシェル コマンドを許可します。これより悪用するのは簡単ではありません)。徹底したセキュリティ レビューが完了するまで、このコードを (できればファイアウォールで保護された) テスト マシンの外部で実行しないでください。
答え2
二重引用符の代わりに一重引用符を使用するようにしてください
system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\'');
シングルクォートは、ほとんどの場合「そのまま」表示されます。詳細については、公式文書では