我遇到在bash一個相當神祕的錯誤,我懷疑有殼擴規的事情。爲什麼bash在輸出中插入「ls /」的輸出?
這裏的故事:在工作中,我一直在負責記錄一個龐大的內部網站,協調公司資源。不幸的是,這些代碼相當醜陋,因爲它已經超出了原來的目的,並且「演變」爲協調公司工作的主要資源。
大部分的代碼是PHP。我寫了幾個幫手腳本來幫助我編寫文檔;例如,一個腳本提取所有php函數中使用的全局php變量。
在所有這些腳本的中心位於「extract_function.sh」腳本。基本上,給定一個PHP函數名稱和一個PHP源文件,它提取並輸出該PHP函數。
現在,這裏的問題:不知何故,作爲腳本提取功能,它基本上是隨機插入的輸出中的ls /
輸出。
例如:
$ ./extract_function my_function my_php_file.php
function my_function {
// php code
/etc
/bin
/proc
...
// more php code
}
更容易混淆的,我只得到這從一個特定的文件中某一特定功能發生!現在,由於該函數非常龐大(超過500行,我說的是當我說代碼很醜時!),但我一直無法弄清楚是什麼原因造成的,或者想出了什麼一個更簡單的ad-hoc功能來產生這種行爲。此外,公司政策阻止我分享實際的代碼。
然而,這裏是我的代碼:
#!/usr/bin/env bash
program_name=$(basename $0);
function_name=$1;
file_name=$2;
if [[ -z "$function_name" ]]; then
(>&2 echo "Usage: $program_name function_name [file]")
exit 1
fi
if [[ -z "$file_name" ]] || [ "$file_name" = "-" ]; then
file_name="/dev/stdin";
fi
php_lexer_file=$(mktemp)
trap "rm -f $php_lexer_file" EXIT
read -r -d '' php_lexer_text << 'EOF'
<?php
$file = file_get_contents("php://stdin");
$tokens = token_get_all($file);
foreach ($tokens as $token)
if ($token === '{')
echo PHP_EOL, "PHP_BRACKET_OPEN", PHP_EOL;
else if ($token == '}')
echo PHP_EOL, "PHP_BRACKET_CLOSE", PHP_EOL;
else if (is_array($token))
echo $token[1];
else
echo $token;
?>
EOF
echo "$php_lexer_text" > $php_lexer_file;
# Get all output from beginning of function declaration
extracted_function_start=$(sed -n -e "/function $function_name(/,$ p" < $file_name);
# Prepend <?php so that php will parse the file as php
extracted_function_file=$(mktemp)
trap "rm -f $extracted_function_file" EXIT
echo '<?php' > $extracted_function_file;
echo "$extracted_function_start" >> $extracted_function_file;
tokens=$(php $php_lexer_file < $extracted_function_file);
# I've checked, and at this point $tokens does not contain "/bin", "/lib", etc...
IFS=$'\n';
open_count=0;
close_count=0;
for token in $tokens; do # But here the output of "ls /" magically appears in $tokens!
if [ $token = "PHP_BRACKET_OPEN" ]; then
open_count=$((open_count+1))
token='{';
elif [ $token == "PHP_BRACKET_CLOSE" ] ; then
close_count=$((close_count+1))
token='}';
fi
echo $token;
if [ $open_count -ne 0 ] && [ $open_count -eq $close_count ]; then
break;
fi
done
是的,我知道我不應該使用bash操縱PHP代碼,但我基本上有兩個問題:
1)爲什麼bash這樣做?
2)而且,我該如何解決?
你在用'if [[-z「$ file_name」]] ||來完成什麼? [「$ file_name」=「 - 」];然後; FILE_NAME = 「的/ dev /標準輸入」; fi'? – sjsam
@sjsadm如果文件名未指定或等於' - ',則從標準輸入讀取。有點像'貓',也使管道更容易。 –