다음 은 제가 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
사람들이 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}'"
여기에는 많은 문제가 있습니다.
- 이는 두 개의 병렬 문자열 리터럴
"echo \"$line\" | awk '{$1=$2=$3=$4="
이며"; print $0}'"
. 이것은 유효한 PHP 구문이 아닙니다. 백슬래시를 사용하여 이 두 개의 큰따옴표를 보호해야 합니다. $
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}\'');
작은따옴표는 거의 항상 내용을 "있는 그대로" 표시합니다. 자세한 내용은 찾을 수 있습니다.공식 문서에서