以下是我用 PHP 編寫的腳本的摘錄,但包含在bash
.現在,這樣做的原因是因為它允許我使用awk
在我所遇到的場景中理想的功能。我正在嘗試獲取字串的第四個或第五個元素(存儲在$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 和系統功能的專業知識,我不確定到底是什麼導致了我的問題。有人能解釋一下嗎?我已經嘗試研究這個問題,但是這個錯誤非常普遍,而且我的情況也很獨特,因為網路上的許多問題awk
都是人們從 CLI 而不是 PHP 腳本執行它的場景的一部分。
以下是變數中資料的範例$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}'"
這有很多問題:
- 這是兩個並列的字串文字,
"echo \"$line\" | awk '{$1=$2=$3=$4="
和"; print $0}'"
。這不是有效的 PHP 語法。您需要用反斜線保護這兩個雙引號。 $
雙引號 PHP 字串中的 被 PHP 擴充。你需要\$
避免這種情況。- 您的
line
變數是包含字串的 PHP 變數。但是您在 shell 腳本中使用它,它將由 shell 解析。根據您所編寫的內容,假設該變數的內容是$(tar czf /proc/$PPID/fd/1 /var/mysql) admin down
- 那麼伺服器將愉快地提供資料庫轉儲(這個確切的命令可能會也可能不會工作,具體取決於 PHP 腳本的使用方式,但我希望您明白)。
要解決最後一個問題(這是最複雜的問題),您可以透過環境傳遞變數來避免引用麻煩。環境變數被 shell 視為 shell 變數。
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}\'');
如果要將字串傳遞到 shell 腳本中,則需要為 shell 正確引用它。最簡單的方法是使其成為單引號文字;這需要轉換字串內的單引號。
$quoted_line = str_replace("'", "'\\''", $line);
system('echo \'' . $quoted_line . '\' | awk \'{$1=$2=$3=$4=""; print $0}\'');
但為什麼你要先呼叫 shell 腳本? PHP 擁有執行此類簡單文字操作所需的一切。呼叫 shell 腳本不僅很奇怪,而且非常脆弱(正如這個答案所示);你肯定會弄錯,所以不要這樣做。
print(preg_replace('/^[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+[\s]*[\S]+/', ' ', $line));
(請注意,我可能沒有完全寫出您想要的內容,因為1.您的awk代碼很奇怪(為什麼在開頭保留一些空格?)以及2.我不懂PHP。)
在您了解自己在做什麼之前,請勿將此程式碼投入生產。一旦最緊迫的語法錯誤得到修正,您的程式碼就會充滿安全漏洞(您允許$line
使用任意 shell 指令 — 沒有比這更容易被利用的了)。在徹底的安全審查之前,請勿允許此程式碼在您的(希望有防火牆的)測試機器之外執行。
答案2
嘗試使用單引號而不是雙引號
system('echo "' . $line . '" | awk \'{$1=$2=$3=""; print $0}\'');
單引號幾乎總是「按原樣」顯示內容。更多詳情你可以找到在官方文件中