在 INI 文件中使用关键字作为变量名

发布于 2024-11-09 15:33:09 字数 353 浏览 3 评论 0原文

我在 INI 文件中有以下内容:

[country]
SE = Sweden
NO = Norway
FI = Finland

但是,当 var_dump()ing PHP 的 parse_ini_file() 函数时,我得到以下输出:

PHP Warning:  syntax error, unexpected BOOL_FALSE in test.ini on line 2
in /Users/andrew/sandbox/test.php on line 1
bool(false)

看来“NO”被保留。还有其他方法可以设置名为“NO”的变量吗?

I have the following in an INI file:

[country]
SE = Sweden
NO = Norway
FI = Finland

However, when var_dump()ing PHP's parse_ini_file() function, I get the following output:

PHP Warning:  syntax error, unexpected BOOL_FALSE in test.ini on line 2
in /Users/andrew/sandbox/test.php on line 1
bool(false)

It appears that "NO" is reserved. Is there any other way I can set a variable named "NO"?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

陌若浮生 2024-11-16 15:33:09

另一个技巧是用它们的值反转你的ini键并使用 array_flip:

<?php

$ini =
"
    [country]
    Sweden = 'SE'
    Norway = 'NO'
    Finland = 'FI'
";

$countries = parse_ini_string($ini, true);
$countries = array_flip($countries["country"]);
echo $countries["NO"];

仍然需要在 NO 周围使用引号(至少),如果这样做,

Norway = NO

您不会收到错误,但 $countries["NO"] 的值将是一个空字符串。

Another hack would be to reverse your ini keys with their values and use array_flip:

<?php

$ini =
"
    [country]
    Sweden = 'SE'
    Norway = 'NO'
    Finland = 'FI'
";

$countries = parse_ini_string($ini, true);
$countries = array_flip($countries["country"]);
echo $countries["NO"];

Still you will need to use quotes around NO (at least), if you do

Norway = NO

you don't get an error but value for $countries["NO"] will be an empty string.

2024-11-16 15:33:09

这可能来得有点晚了,但是 PHP 的 parse_ini_file 的工作方式让我非常困扰,以至于我编写了自己的小解析器。

请随意使用它,但请小心使用它仅经过了浅层测试!

// the exception used by the parser
class IniParserException extends \Exception {

    public function __construct($message, $code = 0, \Exception $previous = null) {
        parent::__construct($message, $code, $previous);
    }

    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

}

// the parser
function my_parse_ini_file($filename, $processSections = false) {
    $initext = file_get_contents($filename);
    $ret = [];
    $section = null;
    $lineNum = 0;
    $lines = explode("\n", str_replace("\r\n", "\n", $initext));
    foreach($lines as $line) {
        ++$lineNum;

        $line = trim(preg_replace('/[;#].*/', '', $line));
        if(strlen($line) === 0) {
            continue;
        }

        if($processSections && $line{0} === '[' && $line{strlen($line)-1} === ']') {
            // section header
            $section = trim(substr($line, 1, -1));
        } else {
            $eqIndex = strpos($line, '=');
            if($eqIndex !== false) {
                $key = trim(substr($line, 0, $eqIndex));
                $matches = [];
                preg_match('/(?<name>\w+)(?<index>\[\w*\])?/', $key, $matches);
                if(!array_key_exists('name', $matches)) {
                    throw new IniParserException("Variable name must not be empty! In file \"$filename\" in line $lineNum.");
                }
                $keyName = $matches['name'];
                if(array_key_exists('index', $matches)) {
                    $isArray = true;
                    $arrayIndex = trim($matches['index']);
                    if(strlen($arrayIndex) == 0) {
                        $arrayIndex = null;
                    }
                } else {
                    $isArray = false;
                    $arrayIndex = null;
                }

                $value = trim(substr($line, $eqIndex+1));
                if($value{0} === '"' && $value{strlen($value)-1} === '"') {
                    // too lazy to check for multiple closing " let's assume it's fine
                    $value = str_replace('\\"', '"', substr($value, 1, -1));
                } else {
                    // special value
                    switch(strtolower($value)) {
                        case 'yes':
                        case 'true':
                        case 'on':
                            $value = true;
                            break;
                        case 'no':
                        case 'false':
                        case 'off':
                            $value = false;
                            break;
                        case 'null':
                        case 'none':
                            $value = null;
                            break;
                        default:
                            if(is_numeric($value)) {
                                $value = $value + 0; // make it an int/float
                            } else {
                                throw new IniParserException("\"$value\" is not a valid value! In file \"$filename\" in line $lineNum.");
                            }
                    }
                }

                if($section !== null) {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret[$section])) {
                            $ret[$section][$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$section][$keyName][] = $value;
                        } else {
                            $ret[$section][$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$section][$keyName] = $value;
                    }
                } else {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret)) {
                            $ret[$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$keyName][] = $value;
                        } else {
                            $ret[$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$keyName] = $value;
                    }
                }
            }
        }
    }

    return $ret;
}

它有什么不同?变量名称只能由字母数字字符组成,但除此之外没有任何限制。字符串必须用 " 封装,其他所有内容都必须是特殊值,例如 noyestruefalseonoffnullnone 有关映射,请参阅代码。

This propably comes a little late but the way PHPs parse_ini_file works bothered me so much that I wrote my own little parser.

Feel free to use it, but use with care it has only been shallowly tested!

// the exception used by the parser
class IniParserException extends \Exception {

    public function __construct($message, $code = 0, \Exception $previous = null) {
        parent::__construct($message, $code, $previous);
    }

    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

}

// the parser
function my_parse_ini_file($filename, $processSections = false) {
    $initext = file_get_contents($filename);
    $ret = [];
    $section = null;
    $lineNum = 0;
    $lines = explode("\n", str_replace("\r\n", "\n", $initext));
    foreach($lines as $line) {
        ++$lineNum;

        $line = trim(preg_replace('/[;#].*/', '', $line));
        if(strlen($line) === 0) {
            continue;
        }

        if($processSections && $line{0} === '[' && $line{strlen($line)-1} === ']') {
            // section header
            $section = trim(substr($line, 1, -1));
        } else {
            $eqIndex = strpos($line, '=');
            if($eqIndex !== false) {
                $key = trim(substr($line, 0, $eqIndex));
                $matches = [];
                preg_match('/(?<name>\w+)(?<index>\[\w*\])?/', $key, $matches);
                if(!array_key_exists('name', $matches)) {
                    throw new IniParserException("Variable name must not be empty! In file \"$filename\" in line $lineNum.");
                }
                $keyName = $matches['name'];
                if(array_key_exists('index', $matches)) {
                    $isArray = true;
                    $arrayIndex = trim($matches['index']);
                    if(strlen($arrayIndex) == 0) {
                        $arrayIndex = null;
                    }
                } else {
                    $isArray = false;
                    $arrayIndex = null;
                }

                $value = trim(substr($line, $eqIndex+1));
                if($value{0} === '"' && $value{strlen($value)-1} === '"') {
                    // too lazy to check for multiple closing " let's assume it's fine
                    $value = str_replace('\\"', '"', substr($value, 1, -1));
                } else {
                    // special value
                    switch(strtolower($value)) {
                        case 'yes':
                        case 'true':
                        case 'on':
                            $value = true;
                            break;
                        case 'no':
                        case 'false':
                        case 'off':
                            $value = false;
                            break;
                        case 'null':
                        case 'none':
                            $value = null;
                            break;
                        default:
                            if(is_numeric($value)) {
                                $value = $value + 0; // make it an int/float
                            } else {
                                throw new IniParserException("\"$value\" is not a valid value! In file \"$filename\" in line $lineNum.");
                            }
                    }
                }

                if($section !== null) {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret[$section])) {
                            $ret[$section][$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$section][$keyName][] = $value;
                        } else {
                            $ret[$section][$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$section][$keyName] = $value;
                    }
                } else {
                    if($isArray) {
                        if(!array_key_exists($keyName, $ret)) {
                            $ret[$keyName] = [];
                        }
                        if($arrayIndex === null) {
                            $ret[$keyName][] = $value;
                        } else {
                            $ret[$keyName][$arrayIndex] = $value;
                        }
                    } else {
                        $ret[$keyName] = $value;
                    }
                }
            }
        }
    }

    return $ret;
}

What does it differently? Variable names may only consist of alphanumerical characters but other than that no restrictions to them. Strings must be encapsulated with " everything else has to be a special value like no, yes, true, false, on, off, null or none. For mapping see code.

烟─花易冷 2024-11-16 15:33:09

有点黑客,但您可以在键名称周围添加反引号:

[country]
`SE` = Sweden
`NO` = Norway
`FI` = Finland

然后像这样访问它们:

$result = parse_ini_file('test.ini');
echo "{$result['`NO`']}\n";

输出:

$ php test.php
Norway

Kind of a hack but you can add backticks around the key names:

[country]
`SE` = Sweden
`NO` = Norway
`FI` = Finland

Then access them like so:

$result = parse_ini_file('test.ini');
echo "{$result['`NO`']}\n";

Output:

$ php test.php
Norway
甜味超标? 2024-11-16 15:33:09

我遇到了同样的问题,并试图以各种可能的方式逃避这个名字。

然后我想起,由于 INI 语法,名称和值都会被修剪,因此以下解决方法可能应该可以解决问题:

NL = Netherlands
; A whitespace before the name
 NO = Norway
PL = Poland

并且它有效;)只要您的同事阅读注释(情况并非总是如此)并且不要意外删除它。所以,是的,数组翻转解决方案是一个安全的选择。

I ran into the same problem and tried to escape the name in every possible way.

Then I remembered that because of the INI syntax both names and values will be trimmed, so the following workaround MAYBE should do the trick:

NL = Netherlands
; A whitespace before the name
 NO = Norway
PL = Poland

And it works ;) As long as your co-workers read the comments (which is not always the case) and don't delete it accidentally. So, yes, the array flipping solution is a safe bet.

梦里的微风 2024-11-16 15:33:09

当字符串中存在单引号组合(例如 't 或 's)时,我收到此错误。为了解决这个问题,我将字符串用双引号括起来:

之前:

You have selected 'Yes' but you haven't entered the date's flexibility

之后:

"You have selected 'Yes' but you haven't entered the date's flexibility"

I was getting this error when there were single quote combinations in the string such as 't or 's. To get rid of the problem, I wrapped the string in double quotes:

Before:

You have selected 'Yes' but you haven't entered the date's flexibility

After:

"You have selected 'Yes' but you haven't entered the date's flexibility"
谷夏 2024-11-16 15:33:09

parse_ini_file 的手册页:

有一些保留字不能用作 ini 文件的键。其中包括:null、yes、no、true、false、on、off、none。

所以不,你不能设置变量NO

From the manual page for parse_ini_file:

There are reserved words which must not be used as keys for ini files. These include: null, yes, no, true, false, on, off, none.

So no, you can't set a variable NO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文