使用 Lua 解析配置文件

使用 Lua 编程语言配置持久性应用程序设置。
51 位读者喜欢这篇文章。
Woman sitting in front of her computer

Ray Smith

并非所有应用程序都需要配置文件;许多应用程序从每次启动时都保持全新状态中获益。例如,简单的实用程序很少需要跨使用场景持久存在的首选项或设置。然而,当您编写复杂的应用程序时,用户能够配置他们如何与应用程序交互以及应用程序如何与他们的系统交互会更好。这就是配置文件的用途,本文讨论了使用 Lua 编程语言实现持久性设置的一些方法。

选择一种格式

关于配置文件,重要的是它们的一致性和可预测性。您不希望以保存用户首选项为幌子将信息转储到一个文件中,然后花费数天时间编写代码来逆向工程最终出现在文件中的随机信息位。

有几种流行的 配置文件格式。Lua 拥有大多数常见配置格式的库;在本文中,我将使用 INI 格式。

安装库

Lua 库的中心枢纽是 Luarocks.org。您可以在网站上搜索库,也可以安装和使用 luarocks 终端命令。

在 Linux 上,您可以从发行版的软件仓库安装它。例如

$ sudo dnf install luarocks

在 macOS 上,使用 MacPortsHomebrew。在 Windows 上,使用 Chocolatey

一旦安装了 luarocks,您可以使用 search 子命令来搜索合适的库。如果您不知道库的名称,您可以搜索关键字,例如 inixmljson,具体取决于您尝试做什么。在本例中,您可以直接搜索 inifile,这是我用来解析 INI 格式文本文件的库

$ luarocks search inifile
Search results:
inifile
 1.0-2 (rockspec) - https://luarocks.org
 1.0-2 (src) - https://luarocks.org
 1.0-1 (rockspec) - https://luarocks.org
 [...]

程序员常犯的一个陷阱是在他们的系统上安装一个库,然后忘记将其与他们的应用程序捆绑在一起。这可能会给没有安装该库的用户带来问题。为了避免这种情况,请使用 --tree 选项将库安装到项目目录中的本地文件夹。如果您没有项目目录,请先创建一个,然后再安装

$ mkdir demo
$ cd demo
$ luarocks install --tree=local inifile

--tree 选项告诉 luarocks 创建一个新目录,在本例中称为 local,并将您的库安装到其中。通过这个简单技巧,您可以将项目使用的所有依赖代码直接安装到项目目录中。

代码设置

首先,在名为 myconfig.ini 的文件中创建一些 INI 数据

[example]
name=Tux
species=penguin
enabled=false

[demo]
name=Beastie
species=demon
enabled=false

将文件另存为 myconfig.ini 到您的主目录,而不是您的项目目录。您通常希望配置文件存在于您的应用程序之外,这样即使当用户卸载您的应用程序时,他们在使用该应用程序时生成的数据仍然保留在他们的系统上。用户可能会手动删除不必要的配置文件,但许多用户不会。因此,如果他们重新安装应用程序,它将保留他们的所有首选项。

配置文件位置在技术上并不重要,但每个操作系统 (OS) 都有一个规范或传统,规定它们应该放在哪里。在 Linux 上,这由 Freedesktop 规范 定义。它规定配置文件应保存在名为 ~/.config 的隐藏文件夹中。为了本次练习的清晰起见,只需将文件保存在您的主目录中,以便易于查找和使用。

创建第二个名为 main.lua 的文件,并在您喜欢的文本编辑器中打开它。

首先,您必须告诉 Lua 您将要使用的附加库放在哪里。package.path 变量决定了 Lua 在哪里查找库。您可以在终端中查看 Lua 的默认包路径

$ Lua
> print(package.path)
./?.lua;/usr/share/lua/5.3/?.lua;/usr/share/lua/5.3/?/init.lua;/usr/lib64/lua/5.3/?.lua;/usr/lib64/lua/5.3/?/init.lua

在您的 Lua 代码中,将您的本地库位置附加到 package.path

package.path = package.path .. ';local/share/lua/5.3/?.lua

使用 Lua 解析 INI 文件

在建立包位置之后,接下来要做的是 require inifile 库,然后处理一些操作系统逻辑。即使这是一个简单的示例应用程序,代码也需要从操作系统获取用户的主目录位置,并建立在必要时如何将文件系统路径传达回操作系统。

package.path = package.path .. ';local/share/lua/5.3/?.lua
inifile = require('inifile')

-- find home directory
home = os.getenv('HOME')

-- detect path separator
-- returns '/' for Linux and Mac
-- and '\' for Windows
d = package.config:sub(1,1)

现在您可以使用 inifile 将配置文件中的数据解析为 Lua 表。一旦数据被放入表中,您就可以像查询任何其他 Lua 表一样查询该表

-- parse the INI file and
-- put values into a table called conf
conf = inifile.parse(home .. d .. 'myconfig.ini')

-- print the data for review
print(conf['example']['name'])
print(conf['example']['species'])
print(conf['example']['enabled'])

在终端中运行代码以查看结果

$ lua ./main.lua
Tux
penguin
false

看起来是正确的。尝试对 demo 块执行相同的操作。

以 INI 格式保存数据

并非所有解析器库都读取和写入数据(通常称为编码解码),但 inifile 库可以。这意味着您可以使用它来更改配置文件。

要更改配置文件中的值,您需要在解析后的表中设置表示该值的变量,然后将表写回配置文件

-- set enabled to true
conf['example']['enabled'] = true
conf['demo']['enabled'] = true

-- save the change
inifile.save(home .. d .. 'myconfig.ini', conf)

现在看一下配置文件

$ cat ~/myconfig.ini
[example]
name=Tux
species=penguin
enabled=true

[demo]
name=Beastie
species=demon
enabled=true

配置文件

保存有关用户希望如何使用应用程序的数据的能力是编程的重要组成部分。幸运的是,这对于程序员来说是一项常见的任务,因此大部分工作可能已经完成。找到一个好的库,用于编码和解码为开放格式,您可以提供持久且一致的用户体验。

这是供参考的完整演示代码

package.path = package.path .. ';local/share/lua/5.3/?.lua'
inifile = require('inifile')

-- find home directory
home = os.getenv('HOME')

-- detect path separator
-- returns '/' for Linux and Mac
-- and '\' for Windows
d = package.config:sub(1,1)

-- parse the INI file and
-- put values into a table called conf
conf = inifile.parse(home .. d .. 'myconfig.ini')

-- print the data for review
print(conf['example']['name'])
print(conf['example']['species'])
print(conf['example']['enabled'])

-- enable Tux
conf['example']['enabled'] = true

-- save the change
inifile.save(home .. d .. 'myconfig.ini', conf)

 

接下来阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,通常同时进行。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.