2015年牢骚

总的来说,这是非常郁闷的一年。

虽然我每年都会感觉很郁闷,但是今年更甚。

所以本来想写总结的,但是还是先写牢骚吧。

生活上,琐事愈发烦多,家庭里的各种琐事都找不到人来处理,或者处理得一团糟,最后各种烂摊子。其实生活上很多事本来就无解,随便怎么处理都不会有完美的结果,如果能分担一下责任,再互相体谅一下,就是很美好的生活,但是如果把决定权都推到我一个人身上,然后事后再抱怨我当初的“错误”决定,积累起来真的是很负面的情绪。
其实自从新租了房子,生活状态就已经不对了,住的太偏严重影响生活质量和节奏,我出差+Home office还好,老婆的生活一塌糊涂,甚至会影响我的。

工作上问题更大,一整年都处于忙忙碌碌的状态,忙得已经影响到了正常的生活,但是却都是无用功,问题在于太多的把时间用在接别人甩过来的包袱,而没有一个很明确的工作长短期目标。虽然我在年初就发现了这个问题,但是很悲哀的没有任何办法解决。
有一些客观的小事更让人抓瞎,笔记本电脑经过3年高强度的折腾,已经不行了,但是离更换还要一年,我时常会在莫名其妙的卡顿2分钟后,涌起一种砸东西的冲动,在家的时候更有“你慢慢卡,我先下楼买个菜”的行动。

去年7月回国后领导就已经变更,今年6月变更后的领导离职,10月新领导入职,虽然交接还算平稳,但是我尴尬的定位还是导致我工作上的郁闷。我越来越觉得我在公司的职业生涯进入了倒计时,如果没有那份合同,可能已经在外面找工作了吧。

最后,北京的雾霾实在是太过分了,还是考虑下移民吧。

借鉴老文章看我们公司的问题

昨天就事论事顺便写了点自己的想法,今天就看到朋友圈里有人转载的一篇老文章——绩效主义毁了索尼

节选几节,映射一下自己公司吧。

从事技术开发的团体进入开发的忘我状态时,就成了“激情集团”。要进入这种状态,其中最重要的条件就是“基于自发的动机”的行动。比如“想通过自己的努力开发机器人”,就是一种发自自身的冲动。

与此相反就是“外部的动机”,比如想赚钱、升职或出名,即想得到来自外部回报的心理状态。如果没有发自内心的热情,而是出于“想赚钱或升职”的世俗动机,那是无法成为“开发狂人”的。

我进公司的时候,公司里还有部分人处于“激情集团”的状态,我也是,不过当时已经有很多新员工是因为“外部的动机”来工作的。但是这也不完全是动机的问题,我知道的情况就是2006年至今公司对于应届生的工资起薪没有任何变体,相信再往前10来年也是这个样子的,对于年平均通胀达到7%的国家来说,就意味着每过8到9年,公司的起薪就降到50%,和20年前相比,现在公司的待遇可能只有四分之一甚至五分之一,激情也是需要吃饱肚子的。

因为要考核业绩,几乎所有人都提出容易实现的低目标,可以说索尼精神的核心即“挑战精神”消失了。因实行绩效主义,索尼公司内追求眼前利益的风气蔓延。这样一来,短期内难见效益的工作,比如产品质量检验以及“老化处理”工序都受到轻视。

索尼公司不仅对每个人进行考核,还对每个业务部门进行经济考核,由此决定整个业务部门的报酬。最后导致的结果是,业务部门相互拆台,都想方设法从公司的整体利益中为本部门多捞取好处。

这几段太直白了,我竟无言以对,好在我们部门是服务部门,不出产品,不过目前公司的策略是全球性的,看着各个工厂出的东西越来越水,证明这两段话是对的。

过去在一些日本企业,即便部下做得有点出格,上司也不那么苛求,工作失败了也敢于为部下承担责任。另一方面,尽管部下在喝酒的时候说上司的坏话,但在实际工作中仍非常支持上司。后来强化了管理,实行了看上去很合理的评价制度。于是大家都极力逃避责任。这样一来就不可能有团队精神。

我又无言以对了,我以为是人多了必然就这样,看来也不尽然。

当时索尼在电视机的市场竞争中处于劣势,几乎到了破产的边缘。即便如此,井深大仍坚持独自开发单枪三束彩色显像管电视机。这种彩色电视机画质好,一上市就大受好评。其后30 年,这种电视机的销售一直是索尼公司的主要收入来源。

但是,“干别人不干的事情”这种追求独自开发的精神,恐怕不符合今天只看收益的企业管理理论。索尼当时如果采用和其他公司一样的技术,立刻就可以在市场上销售自己的产品,当初也许就不会有破产的担心了。

追求股东利益和营业额的现代公司恐怕无法接受这种理念吧,现在的模式基本都是小微企业搞创新,大公司凭借资本优势并购并规模经营。

在索尼充满活力、蓬勃发展的时期,公司内流行这样的说法:“如果你真的有了新点子,来。”也就是说那就背着上司把它搞出,与其口头上说说,不如拿出真东西来更直接。但是如果上司总是以冷漠的、“评价的眼光”来看自己,恐怕没有人愿意背着上司干事情,那是自找麻烦。如果人们没有自己受到信任的意识,也就不会向新的更高的目标发起挑战了。在过去,有些索尼员工根本不畏惧上司的权威,上司也欣赏和信任这样的部下。

深有同感,过去几年里真没少“自找麻烦”。

幸好我还有自己的blog

最近工作上非常不开心。

回国快一年了,什么也没干!真的什么也没干,回国前还很天真地觉得回国后能当个吉祥物,现在则连吉祥物都算不上。在稍微成规模的企业中,必须找到自己的定位,然后去适应。出国前我放弃了自己的位置,回来后为了容纳我这个多余的人,凭空造出一个位置给我,结果就是:我根本无法成为公司正常运转中的一个环节。

不过这也不是不开心的主要原因,毕竟下决心出国前就想到了可能有的问题,不开心则是因为一则流言。

大意是,某负责人把公司的客户拉走,然后让下属在下班时间用公司设备替这个客户干活然后自己收线。

流言只是流言,没有证据,不过根据我对信息源和当事人的了解,我深信不疑,而且他干出这种事也是早晚的事情。可是我为什么会生气呢,虽然我总说我对公司没什么感情了(not any more),但是毕竟待了8年了,而且还要至少再待2年,看着一步步堕落到现在这样,还是挺烦的,觉得自己的逼格也跟着下降了。

记得刚来公司时,虽然规模没有这么大,工作压力也没有现在这么高负荷(意味着人会稍微懒一点),但是所有人在工作时都会抱着一种优越感,这种优越感不是说我在某个老牌外企就怎么怎么样,而是说我以我的工作自豪,我认同我同事的工作方法,态度,职业道德,我也愿意以这种方法工作。

以差旅报销为例,我进公司时的07年报销制度还是一种半自觉的状态,并不会有很严格的流程和审查,再之前则完全是凭自觉。后来逐渐收紧,当2013年公司决定所有住宿酒店全部要从携程上预订时,比较新的员工在抱怨自己灰色收入要变少了,而我——相信还有一部分老员工——则觉得公司和员工之间的信任完全没有了。

这就像是一个恶性循环,我相信如果流言这件事发生在07年,根本不会发生,这种同事根本不会当上负责人,他的下属也不可能被他胁迫做这种事情,所有知道这件事的人会马上举报(虽然那时候没有什么合规部),不到一周这个人就会被开除,然后流言会变成他为什么被开,然后大家引以为戒。

好了,牢骚和感伤到处为止,我来试着分析一下这件事产生的必然性和偶然性原因吧。

大环境

这种“吃里扒外”——抱歉,找不到更适合描述的词了——的行为在社会上并不是什么少见的行为,我还特意去查了查,遇上这种事,通常只能以违反劳动合同条款为由开除,如果合同中并没有相关的规定,甚至都没有办法。法律上对类似的行为没有处罚,相近的是职务侵占罪,针对是侵占固定资产,如果操作得当,比如和客户签订合同的公司自己并不是法人,就无法追究刑事责任。所以这种行为的违法成本相当低,大不了开除或者被扣点工资,只要捞一笔大的就可以了。

公司管理

最近几年,公司在全球层面上已经成功地转变成了销售为导向,利润和营业额为主要考核指标的模式,对于公司来说没什么不好,但是当过于关注某一项指标时,其他方面就会出现一些问题。我想公司也意识到了这一点,所以最近几年,财务部门收紧政策,又新建了合规部门。但是全球的政策到了中国明显水土不服,至少在我们事业部水土不服,花地力气不小,没盯到点上,其实中国的国情,举报有奖,全解决了。

个人问题

如果只论人缘,这次这哥们在公司历史上绝对能算得上倒数前三名的,我觉得这并不只是个性等个人原因,也意味着他在做事的方法上和公司的整个企业文化不和。我想虽然他在前一个企业的时间还没有在我们公司长,但是明显他更受前面企业的影响,而没有被我们同化。然后在企业文化冲突的过程中,他感受到的阻力没有获得得利益大,于是胆子越来越大,导致了这种越线的事情发生,这也和我们工程师团队总体性格上偏妥协有关系。

领导问题

虽然不想批评自己的领导,但是发生这种事情领导的责任是跑不了的。但是我的确不知道领导是怎么想的,到现在我还有2个主要疑问:
领导是否知道他被如此多的人反感,以及他之前做的一些过分(但是不越线)的事情。
领导是默许他的做法以保持团队内的平衡,还是完全觉得这些事是对的。

整个企业文化的转变

从什么样转化什么样不知道,我能看到的是,由于雇员人数的大幅增长,单体的效率在下降,更多地靠制度而不是自律来管理日常工作,满足制度的前提下,每个人都不愿意去“多管闲事”。
所以这种事情发生时:知情人尽量躲开,避免惹祸上身。
事情发生后:大家传传八卦,等着看公司的态度,继续避免惹事上身。

而我呢,在压抑了最开始去找合规部门举报的冲动后,我决定看,如果这个事情依然没有一个很符合“正常价值观”的结果,那我离开公司也是倒计时状态了。

三坐标转台算法的思考

明天要去一家客户解决转台问题,当其他同事搞了四个月还没有搞好,我也没有信心去一次就能搞定。所以我今天就在做一些准备,就想从原理上先解决一下转台的算法,这样到了现场就比较容易地分析问题出在哪里。

作为一个附加的设备,控制柜中并没有能直接读出坐标值的功能,读到的值依旧是XYZ三个轴上的读数头的示值。而转台唯一能提供的就是当前旋转的角度。

而校准转台时又可以得到转台相对于机器坐标系的轴线坐标\[\begin{cases}x=x_0+it\\y=y_0+jt\\z=z_0+kt\end{cases}(t\in R)\],那么可以得到当转台旋转角度为\(0^\circ\)时的坐标系仿射矩阵为(抱歉这里打成转置矩阵了,我用的算法库里行列就是反的╮(╯_╰)╭)\[A=\begin{bmatrix}\frac{k}{\sqrt{1-j^2}}&0&\frac{-i}{\sqrt{1-j^2}}&-x\\\frac{-i*j}{\sqrt{1-j^2}}&\sqrt{1-j^2}&\frac{-j*k}{\sqrt{1-j^2}}&-y\\i&j&k&-z\\0&0&0&1\end{bmatrix}^T\]。

当转台旋转了\(\theta^\circ\)时,坐标系为原坐标系乘以一个旋转矩阵\[A’=A*\begin{bmatrix}1&0&0&0\\0&\cos{\theta}&-\sin{\theta}&0\\0&\sin{\theta}&\cos{\theta}&0\\0&0&0&1\end{bmatrix}\]

因为三坐标取点是离散的,那么每个角度采的点只是\(\theta\)不同而已,那么就可以通过\(A’\)矩阵将每个点转换到转台的坐标系上。

新工作来临了

刚才领导语气沉重地电话通知,说明年其他工作先放放,先把自动化生产线的东西搞一搞,老板看了竞争对手的展会后很不高兴,觉得我们这面落后了。

我到是蛮想搞的,虽然充其量就是一个本科毕设量级的东西,不过相比于现在做的连本科毕设都不如的东西,还算有点意思吧。

第一步是做预算和方案,然后今后会写一些机械手和自动化相关的东西了吧。

落榜了

申请前也做过落榜的心理准备,不过这么快还是有点措手不及。本来估计起码能混个面试,然后面试可能被刷或者待定,结果却是直接没有面试资格。

到现在依旧不知道问题出在哪里,几周或几个月后,可以申请查询。目前我能猜到的理由是,管理经验过少,相对的年龄偏大,不过不管怎么样,生活还要继续,申请准备的过程其实也有很多收获,希望明年我还有这个意愿。

数据不会说谎——清华MBA自测统计结果

最近想念个MBA,刚刚交了面试申请,然后清华的MBA网站上线了一个自评系统,由于上线在申请截止时间以后,官方报名群里几个人抱怨这个没有用,而且里面并没有给出什么结论,只是把你的一些资料放在所有参加自测的人里面相比较,给一个比例。虽然说话的都说没用,不过还是能看出一些东西的。

首先,保守估计报名或者有报名意愿的应该有4000人左右,目前参加测试的只有280人,先要假设这280人是一个随机均匀的样本,从结果看来这个假设是成立的。

可以看这三个结果:

行业分布——清华的官网上解释录取标准里不包括行业和学科的评价,从数据来看,这是对的,参加测试的人员的行业分布和去年录取人员的行业比例惊人的相似,金融、咨询、能源、科技新媒体比例稍高,但是差的不多,房地产、非营利组织、不容易归类的其他行业稍低。

制造业

 

 

职能部门——这个趋势图几乎一致,不过百分比有些出入,不是特别明显,唯一就是去年公务员全军覆灭。

职位

学科——这个几乎是一模一样了。

学科

OK,在证实了这个分布基本是可以参考的以后,不同的分布就可以看出在录取上的取舍标准了。

学校——参加测试的分布和真实情况吻合与否无法判断,不过大概是对的,首批985才10所左右,985有30所左右,211有一大批,普通本科更是多,奇怪的是211学校的报名人数少很多。

但是再看去年录取的学生,普通本科的比例大大下降,首批985的比例大为上升。

所以本科学校的排名是个很重要的参考项。

院校

 

 

学历——这个已经很明显了,本科是标配,影响不大,专科和结业的很受影响,研究生还是有些优势。学历

 

职位——职位越高,机会越多,其实这个也从侧面证明了参考数据的有效性。级别?学历

 

 

 

 

 

 

 

 

Python与DotNet交互环境的搭建以及一些问题

之前一直工作在.NET环境下使用C#,在稍微接触了Python以后被迷住了,实际上到现在除了一个演示滤波的小玩具其他什么也没做,不过参考之前的一些经历,觉得把环境搭好比较重要,方便以后随时地开始玩(造)。
在经历了开始的兴奋阶段后,开始琢磨我可以用这个做些什么,当然对我日常工作很有帮助,但是鉴于我的工作大部分时间要在客户的工作站上完成,所以有了以下需求:
1.需要打包成exe部署到客户端。
2.需要可以和C#交互以便复用之前的一些工作,避免重复开发引起的功能不兼容,以及使用对方没有的功能。

解决方案有3个(未完全测试):

1.IronPython,在.NET下实现Python,这样可以在Python中使用所有的.NET库,当然支持所有Python语法。
2.Microsoft Scripting功能以及IronPython.dll,实际上是在.NET程序中加入了脚本支持功能。
3.CPython+Python for .NET,实际上通过一个接口可以在Python中调用.NET下的CLR,最后再用py2exe打包。

先声明:环境搭建好后还没有经过完全测试,没办法保证可以部署到其他设备上正常使用。会慢慢找机会测试。

方案一——将IronPython集成到.NET开发环境:

首先安装IronPython,安装好后可以使用自带的或其他IDE,我试了Eclipse+PyDev,和SharpDevelop,PyDev不支持可视化图形界面,而SharpDevelop没办法加BreakPoint(不知道是不是我不会设置,求大神帮助)。

一个简单的例子如下:

import sys
sys.path.append("C:\Program Files (x86)\IronPython 2.7\Lib")
sys.path.append("C:\\Program Files (x86)\\IronPython 2.7\\lib\\site-packages")
sys.path.append(r"C:\Program Files (x86)\IronPython 2.7")
sys.path.append(r"C:\Program Files (x86)\IronPython 2.7\DLLs");
sys.path.append(r"C:\Python27\Lib\site-packages")
import clr
clr.AddReference('mtrand.dll')
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
#clr.AddReference('SPInterface')
clr.AddReference('System.IO')
clr.AddReference('System')


from System.Diagnostics import Trace
from System import Console
#import SPInterface as SP
import numpy as np

print 'Hello World'

如果有多种语言的经验,这里比较好理解
sys.path.append类似C编译时的头文件Include路径
clr.AddReference就是.NET里的添加引用
而from System.Diagnostics import Trace则是类似于C#里的
using System.Diagnostics

里面注释掉的几行是我在C#之前写的库,经测试可以正常使用(而且我的库依赖mathdotnet,在同文件夹下貌似自动识别了)。

优点:比较方便,更偏向于.NET,虽然使用的是Python语法。可以很方便的搭建界面。

缺点:由于不兼容CPython,所以很多库用不了,numpy刚刚支持没多久,而matplotlib不支持,实际上感觉完全不能发挥Python的优点。

方案二——在.NET开发环境使用Python脚本:

第一步同上,安装IronPython,在安装文件夹下有Platforms\Net40文件夹,在.NET项目中引用其中的Microsoft.Scripting.dll和IronPython.dll,可以去网上搜搜例子,就可以在代码调用Python脚本了,一个简单的例子:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using IronPython.Hosting;

namespace testIron2
{
   public partial class Form1 : Form
    {
        Microsoft.Scripting.Hosting.ScriptEngine engine;
        public Form1()
        {
            InitializeComponent();
            var source =
@"
import clr
clr.AddReference('mtrand.dll')

def SysPath():
    import sys
    return sys.path
def ImportNumpy():
    import numpy
            ";

            engine = Python.CreateEngine();

            var sp = engine.GetSearchPaths();
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\DLLs");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\Lib");
            sp.Add(@"C:\Program Files (x86)\IronPython 2.7\Lib\site-packages");
            engine.SetSearchPaths(sp);

            var scope = engine.CreateScope();
            var ops = engine.Operations;

            engine.Execute(source, scope);
            dynamic py = scope;

            // Calling into IronPython works fine + sys.path looks correct
            dynamic syspath = py.SysPath();

            // EXCEPTION when we try to "import numpy":
            // "The type initializer for 'NumpyDotNet.NpyCoreApi' threw an exception.",
            // "Unable to load DLL 'NpyAccessLib': The specified module could not be found. (Exception from HRESULT: 0x8007007E)"
            dynamic numpy = py.ImportNumpy();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            engine.Execute(textBox1.Text);
        }
    }
}

这段代码是当时在网上找的,很抱歉忘记原始链接了,里面的注释应该是原作者遇到的问题,我遇到了应该是相同的,异常信息是无法读取库,原因是没有mtrand.dll文件,stack overflow上有解答,貌似是因为C编译库的问题,所以要在Python命令字符串中加入

clr.AddReference('mtrand.dll')

可以看出来,和方案一其实是一样的,所以优点是熟悉C#代码的可以尽量的用C#,脚本只是辅助方便现场调试修改。
貌似所有在IronPython下安装的库会有DLL版,这意味着我在纯C#下可以用numpy了?还没有测试。

缺点:所有方案一的缺点,而且Python代码无法调试,只有看异常信息然后从头运行。

方案三:在有.NET环境下安装Python for .NET

这个是目前看起来最方便的,只需要装一个库,就可以用类似IronPython的方式来调用.NET环境,包括我自己的库。同时保留所有之前的功能。简单例子如下:

# encoding: utf-8
'''
Created on 2014年5月14日

@author: zcxsun
'''
# import sys
#sys.path.append(r"C:\Qt\Projects\sp_reader\sp_reader\bin\Debug")

import clr
# clr.AddReference('SPInterface')

from System import String
#import SPInterface as SP

a = String('   a,b,c,d,e,f,g   ')
b = a.Trim()
c = String(b).Split(',')
for i in c:
    print i
# SP.SP_Path.folder_name = r'C:\Users\Public\Documents\Zeiss\CALYPSO\sp_filter\conf\spiConf.xml'
# SP.SPI.init()
# for i in SP.SPI.elements:
#     print i.identifier

print 'finish'

注释部分是调用我自己库的代码,需要注意的是很多地方需要显式转换,所以不能用类似a.Trim().Split(‘,’)这样的语法,只能String(a.Trim()).Split(‘,’)这样。因为用type(String(‘ a,b,c ‘).Trim())得到的类型不是Trim应该返回的String类型,而是<type ‘unicode’>

这个感觉应该是最方便的,在Eclipse下显示良好,调试良好。不确定的是py2exe后效果如何。

结论:目前感觉方案2针对我的情况是最优的,方案3则是用来实现功能测试用最方便的,所以未来的短期计划是用PyDev调用一些自己的库,用来设计和实现算法和功能。实验好了后在C#中实现,然后将脚本功能放在文件中调用。

当然,这样的性能应该是有一定问题的,不过对于我的情况是够了。

 

使用Python模拟高斯滤波过程并生成视频

Python在这类工作上的方便程度真的是——爽。

这里模拟的是低通高斯滤波的过程。

代码如下:需要numpy 和matplotlib,如果想保存成视频文件还需要下载ffmpeg

# encoding: utf-8
'''
Created on 2014年5月1日

@author: zcxsun
'''
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
plt.rcParams['animation.ffmpeg_path'] = r'C:\sunxin\ffmpeg_x64\bin\ffmpeg.exe'

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()

speed = 1
size = 360
a = np.arange(size) *np.pi/180
b = np.zeros(size)
x = -0.1
for i in range(1,14,2):
    x = x*(i-2)/i
    b += x * np.sin(a*i)
b+= 0.02 * np.sin(a*50) + 0.01 * np.sin(a*150)
fix_signal = b

hamonic = 15

len = max(1, size/hamonic/2)
print len
scale = 0.3*len+0.8;
scale2x = -0.5/scale/scale
win =  np.exp( pow(np.arange(2*len+1)-len,2)*scale2x)
win/=sum(win)
move_gauss = win
print win.size
filtered_data = np.convolve(b, win, 'same')


#set the axis arrange
y_max = 0.4
ax = plt.axes(xlim=(0, 360), ylim=(-0.2, y_max))
line_gauss, = ax.plot([], [], lw=2)
line_filtered, = ax.plot([],[],lw=2)

plt.plot(fix_signal)

# initialization function: plot the background of each frame
def init():
    line_gauss.set_data([],[])
    line_filtered.set_data([],[])
    return line_gauss,line_filtered,
# animation function.  This is called sequentially
def animate(i):
    n = np.floor(i*speed)
    line_gauss.set_data(n+np.arange(0,win.size),win + (y_max-0.03-win.max()))
    line_filtered.set_data(np.arange(0,n),filtered_data[0:n])
    return line_gauss,line_filtered,
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=int(np.floor(size/speed)), interval=10, blit=True)

FFwriter = animation.FFMpegWriter(fps = 15)
path = r"C:\Users\Public\Documents\filter_show_hamonic_" + str(hamonic) + ".mp4"
anim.save(path, writer = FFwriter)
#
# plt.show()
print 'finish'

 

解决DOKUWIKI中TSQL标签错误高亮的问题

昨天试验性的装了个wiki,感觉用来记笔记比Blog要方便而且专业的多了。

今天往里面插入代码的时候却郁闷了,dokuwiki使用的是geshi高亮,先是sql没有datetime和nvarchar关键字,我在插件目录里修改完了却不生效。然后用tsql支持这些关键字,但是会把我inspection的in当作关键字高亮,改了半天依然无效,搜了半天,原来……人家geshi已经集成了,不是当作插件来运行的,我下载了插件改了半天(\plugin\geshi\geshi\),但是实际上生效的是\inc\geshi\,找到位置后修改,OK。

原因是因为像in, and, or在这个文件里被当作运算符号来处理,所以和+-=一类的放到了SYMBOL里,对于a+b,肯定是高亮加号的,但是mine总不能高亮中间的in吧。

办法一:把这些字符类的符号前后加空格:’IN’ -> ‘ IN ‘因为敲代码时遇到这些逻辑单词肯定要高空格的,这样匹配的时候就不会匹配单词的一部分了。

方法二:把这些字符类的SYMBOL移到KEYWORD里去,单独建一个组,然后在STYLE那里给个组设置一下,改成和SYMBOL一样。