越努力 越幸运

【译】JSON and Go

一、问题背景

二、解决方案

三、参考资料

JSON and Go

编写 PHP 扩展入门

一、环境

文中示例 PHP 扩展的环境为:

  • Mac OS
  • PHP7

在开始编写 PHP 扩展前需要准备如下环境:

  • PHP7 源码
  • 使用 brew 安装 libtool

二、编写

环境准备好以后,就可以开始编写 Hello world 程序了,需要经历如下步骤:

1. 进入 PHP 源码文件

$ cd php-7.0.5/ext

2. 创建扩展骨架

$ ./ext_skel --extname=helloworld
Creating directory helloworld
Creating basic files: config.m4 config.w32 .gitignore helloworld.c php_helloworld.h CREDITS EXPERIMENTAL tests/001.phpt helloworld.php [done].

To use your new extension, you will have to execute the following steps:

1.  $ cd ..
2.  $ vi ext/helloworld/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-helloworld
5.  $ make
6.  $ ./sapi/cli/php -f ext/helloworld/helloworld.php
7.  $ vi ext/helloworld/helloworld.c
8.  $ make

Repeat steps 3-6 until you are satisfied with ext/helloworld/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writing
code and repeat the last two steps as often as necessary.

使用 ext_skel 命令生成扩展骨架后,给出了非常详细清晰的后续流程说明,基本上跟着这些步骤来着就可以完成 Hello world 扩展程序了。

一句 awk 获取 ini 文件的值

一、问题背景

使用脚本语言操作 ini 文件已经有很多现有的方案了,比如 pythonConfigParser 模块等。现在有一些 shell 脚本用于执行自动化工作,但是每个模块都有自己的配置文件,修改起来很不方便,能不能收敛到一个配置文件?同时不使用 python 脚本,直接使用 awksed 这样的 shell 脚本来搞定呢?

二、解决方案

假设 ini 文件 test.ini 为如下:

[section1]
ip=10.11.12.13
port=1234

[section2]
ip=10.21.22.23
port=5678

为了能够获取 section2 下 ip 的值,需要如下几个步骤:

  1. = 分隔每行
  2. 找到 [section2]
  3. 满足 1 以后,从此开始找到第一个 ip
  4. 打印 ip 对应的值,停止,退出

1. 分隔每行

在 awk 里可以使用 -F 来指定每行的分隔符号,如下:

awk -F '=' '{print $1}' test.ini
# 打印结果
ip
port

[section2]
ip
port

2. 找到 [section2]

为了找到对应的 [section2]ip 的值,使用 awk 的正则表达式,关于此可阅读参考资料。

在 awk 里正则表达式的基本语法为:

awk -F '=' '/'section2'/{print $1}' test.ini
# 打印结果
[section2]

即使用 /正则式/{表达式} 这种形式来书写,使用 // 将正则式包装起来,只有当正则式匹配时才会执行后面的表达式。

为了找到 [section2] 行,所以需要书写这样的语句:

awk -F '=' '/\['section2'\]/{print $1}' test.ini
# 打印结果
[section2]

由于 [] 已经在正则表达式里被使用了,所以这里需要使用 \ 对其进行转义。

3. 找到 ip 对应的值

同理,要找到 ip 对应的值就很容易了:

awk -F '=' '$1~/'ip'/{print $2}' test.ini
# 打印结果
10.11.12.13
10.21.22.23

这句话的意思是,被 = 分隔后的,第一个串如果与 ip 匹配,则打印该行的第二个串,也就是 ip 对应的值,在 awk 的正则表达式里,使用 ~ 来表示匹配。

4. 完美解决

两个独立的语句书写起来是没有什么难度的,那么要把它们组合起来完成需求该如何做呢?

awk -F '=' '/\['section2'\]/{t=1}t==1&&$1~/'ip'/{print $2;exit}' test.ini
# 打印结果
10.21.22.23

结果如预期,完美解决!

但是这是为什么呢?

语句执行后,首先找到匹配 [section2] 的行,这时设置一个变量 t 并给其赋值,当 t 被赋值后,就会判断是否相等,相等后就会执行 && 后面的语句,即找到第一个与 ip 匹配的行,输出对应的值,并结束整个语句的执行。

三、参考资料

AWK 简明教程

The GNU Awk User’s Guide

map 迭代器实效问题

一、问题背景

对于 C++ STL 中的 map 都不陌生,但是对其 erase 操作后的迭代器使用是否遇到过问题呢?看如下代码:

map<string, int> m;
map<string, int>::iterator it = m.begin();
for( ; it != m.end(); ++it)
{
    m.erase(it);
}

这样操作会引起程序崩溃,因为 erase 后迭代器就实效了,再根据迭代器进行操作当然就会导致程序崩溃。

二、解决方案

解决这个问题的方法也很简单,如果熟悉 it++ 操作的含义,就会瞬间想到该怎么做,代码如下:

map<string, int> m;
map<string, int>::iterator it = m.begin();
for( ; it != m.end(); )
{
    m.erase(it++);
}

这样操作就不会导致迭代器实效了,前面代码等同于如下代码:

map<string, int> m;
map<string, int>::iterator it = m.begin();
for(; it != m.end(); )
{
    map<string, int>::iterator tmp = it;
    ++it;
    m.erase(tmp);
}

即在 erase 操作前先将其迭代器保存起来,然后递增后再操作,这些步骤组合在一起也即是 it++ 的含义。

那些踩过的 PHP 坑之 array_merge 函数

一、函数 array_merge 坑在哪里

最近在使用函数 array_merge 合并两个数组时,得到的结果总是不确定,代码如这样:

$arrResult = array_merge($arrInput1, $arrInput2);

如果已踩过这个坑,肯定能一眼看出代码的潜在问题,以及如何避免,但是问题究竟是什么呢?变量 $arrResult 的值会根据函数 array_merge 的两个参数的类型及值而变化,如:键为数字的字典null 等,详细问题解释说明请继续往下看!