包括分词、词性标注、命名实体识别和词义消歧。使用词性标注便于判定每个词的语法范畴。词义标注、词义消歧主要解决多语境下的词义问题,因为在多语境下一个词可能会拥有很多含义,但在固定情境下意思往往是确定的。在中文情境下词法分析是最核心的一部分,只有做好分词工作,剩下的工作才能顺利进行。
词法分析的实现主要通过基于规则、基于统计、基于机器学习的方法。
lexical analysis是计算及科学中将字符序列转换为标记(token)序列的过程。进行词法分析的程序或者函数即为词法分析器简称lexer词法分析器一般以函数形式存在,供语法分析器调用。
b=1
00
101:a=2*(1+3)
IF(b>10) THEN
a=1
ELSE IF(b>=5) THEN
a=2
ELSE
GOTO 101
#coding=utf-8
import sys
import string
key_word = ['IF','THEN','ELSE','GOTO'] #定义关键词
operator = ['=','+','>=','*','>'] #定义运算符
delimiters = [':','(',')'] #定义界符
#预处理函数,对例程进行预处理,去掉多余的空格、注释
def preprocess(file_name):
try: #try except 使程序不会因为异常而中断
fp_read = open(file_name,'r') #打开需要分析的文件
fp_write = open('preprocess.txt','w')
sign = 0 #每当上一个字符为空格时,将sign变为1,通过这样来保证每个需要空格的地方不会有多余的空格
while True:
read = fp_read.readline() #循环读取每一行字符
if not read:
break #如果没有读取到任何东西直接结束循环
length = len(read) #获得当前字符串的长度
i = -1
while i < length - 1: #循环读取每个字符
i+=1
if read[i] == ' ':
if sign == 1: #读取到空格,如果sign为1说明上一个字符也是空格,那个可以忽略当前空格
continue
else: #如果sign不为1,说明上一个字符不是空格,那么就输出当前空格
sign = 1
fp_write.write(' ')
elif read[i] == 't': #同上读取到空格的操作,对于水平制表符(tab)同样输出为一个空格,如果已经输出过一个空格了那就选择跳过
if sign == 1:
continue
else:
sign = 1
fp_write.write('')
elif read[i] == 'n': #同上读取到水平制表符(tab)的操作
if sign == 1:
continue
else:
sign = 1
fp_write.write(' ')
elif read[i] == '/' and read[i+1] == '*': #如果读取到/* 即注释
i = i + 2 #从星号之后的第一个字符开始遍历直到读取到下一对注释
while True:
if read[i] == '*' and read[i+1] == '/':
break
i = i + 1
i = i + 1 #遍历完之后i停留在左斜杠,所以需要+1达到下一个字符
elif read[i] == '\': #如果读取到续行符,之所以是双斜杠因为右斜杠是转义字符,双右斜杠等于单右斜杠,即续行符
break
else: #除了以上这些就直接输出字符就好
fp_write.write(read[i])
sign = 0
fp_write.write('#')#在最后输出一个井号
except Exception:
print('Errors')
# K:关键字 I:标识符 C:常数 O:运算符 P:界符 L:标号
def process(file_name):
try:
fp_read=open(file_name,'r') #打开预处理之后得到的文件
fp_write=open('result.txt','w') #打开一个新的文件,为了将得到的二元式表输入进去
lines = fp_read.readlines() #依旧是按行读取
i = -1
for line in lines: #逐行遍历
length = len(line) #获得当前行字符长度为了遍历每个字符
while i < length - 1:
i+=1
if line[i] == ' ': #当前字符为空格,直接跳过
continue
if line[i] in delimiters: #当前字符在最开始定义的界符集中,那么就直接输出(P,当前字符)
print('(P,',line[i],')',file=fp_write)
continue
if line[i] in operator: #当前字符在运算符集中
if line[i-1] in operator: #判断运算符,祥见程序之后注释(1)
continue
print('(O,',end='',file=fp_write) #end=''实现print不换行,file=fp_write实现将print的内容输出到文件中
if line[i+1] in operator:
print(line[i],line[i+1],')',sep='',file=fp_write) #sep=''实现print连续输出不加空格,为了输出>=而不是> =
else:
print(line[i],')',file=fp_write)
continue
if line[i-1].isdigit(): #判断数字,祥见程序之后注释(2)
continue
if line[i].isdigit():
t = i
while line[i].isdigit():
i+=1
if line[i] == ':' or line[i] == '#':
print('(L,',end='',file=fp_write)
else:
print('(C,',end='',file=fp_write)
i = t
while line[i].isdigit():
print(line[i],end='',file=fp_write)
i+=1
print(')',file=fp_write)
i-=1
continue
j = 0
temp = '' #判断关键词及标识符,详见程序之后注释(3)
while True:
if line[i] == ' ' or line[i] in operator or line[i] in delimiters:
break
else:
j+=1
i+=1
if i > length-1:
break
temp = line[i-j:i]
if temp in key_word:
print('(K,',temp,')',file=fp_write)
else:
if temp == '#':
break
print('(I,',temp,')',file=fp_write)
i-=1
except Exception:
print('Error')
def main():
preprocess('source.txt')
process('preprocess.txt')
if __name__=='__main__':
main()
项目部分 python防止程序中断
- 判断运算符,整体思路是当识别到当前字符是运算符的时候,判断下一个字符是否也是运算符,如果是运算符的话,就连续输出两个运算符,如果不是,就单独输出,需要加一个if判断上一个字符是否为运算符,若是,则直接跳过,因为如果是的话当前运算符肯定已经输出过了。
- 判断数字,在程序中数字分两种,一是给变量赋的值,二是程序段前的标号,通过观察这两种数字前后紧邻的符号来确定类型。当读取到数字的时候,程序会先保存一下当前的i值,然后循环一次得到当前数字是几位数,以便得到最后一位数之后是冒号或者#来判断当前数字是标号还是常数,之所以保存了i的值,就是为了在判断完成之后,让i的值复位,然后重新循环读取整个数字。在读取完整个数字之后让i-1
- 判断关键词和标识符,定义j来表示关键词或者标识符长度,temp为空的字符串,当遇到空格、运算符、界符就跳出循环line[i-j:i]即为从i-j到i对应的字符串,也就是遍历遇到要么是关键词要么是标识符的字符串,如果这个字符串在key_word数组中,那么就是关键词,否则就是标识符。
每次加载之前都需要将之前搜索过的*号加载进来,进行去重。
def have_already_search_no(out_put_tb):
my_insert = con_oracle()
conn_insert = my_insert[0]
cur_insert = my_insert[1]
cmd = "select distinct *号 from xyz." + out_put_tb
cur_insert.execute(cmd)
all_no = set([i[0] for i in cur_insert])
print('已处理*号加载完毕!')
cur_insert.close()
conn_insert.close()
return all_no
python中set()集合,里面不含重复元素,接收一个list作为参数。可以使用add(key)向集合中添加元素,重复元素自动过滤。可以通过remove(key)方法删除元素。set还可以像数学上那样求交集和并集。
list1 = ['a', 'b', 'zhang', 'kang'] list2 = ['a', 'b', 'c', 'd'] s1 = set(list1) s2 = set(list2) #交集使用& s3 = s1&s2 #并集使用| s4 = s1|s2
获取已导入的*号
def import_info():
my_con = con_oracle()
conn = my_con[0]
cur = my_con[1]
cmd = "select **人, *号 from 库.zhaiyao where *号 is not null and **人 is not null"
cur.execute(cmd)
all_no = []
for i in cur:
pr = i[0]
no = i[1]
all_no.append(no)
cur.close()
conn.close()
**人地址和所有 所在地分析
具体逻辑:**人如有注册地,则使用该地址,如果没有则提取出 *告的省市县地址,然后对??提取省市县地址信息进行比对分为两种:1.同省不同市 2.不同省不同市。
def BG_addr_analysis(all_info, BG, reg_addr_info):
result1 = [] #同省不同市
result2 = [] #不同省市
BG_addr_info1 = ['', '', '']
BG_addr_info2 = ['', '', '']
if reg_addr_info:
reg_addr = reg_addr_info[0][0]
BG_addr_info1 = person_address(reg_addr)
BG_addr_info2 = person_address(BG)
BG_addr_info1_clean = [i for i in BG_addr_info1 if i]
BG_addr_info2_clean = [i for i in BG_addr_info2 if i]
#先注册地提取一次省市,然后??名字提取一次省市,比较一下哪个信息提取得多就用哪个
if len(BG_addr_info1_clean) >= len(BG_addr_info2_clean):
final_addr_info = BG_addr_info1
else:
final_addr_info = BG_addr_info2
if len(all_info) == 0:
return [], []
else:
for info in all_info:
C_h1 = KillNone(info[4])#做出????单位
C_h2 = KillNone(info[5])#执行??
C_h_final = C_h2
if not C_h_final:
C_h_final = C_h1
C_h_a = person_address(C_h_final)
C_h_a_prov = C_h_a[0]
C_h_a_city = C_h_a[1]
BG_a_prov = final_addr_info[0]
BG_a_city = final_addr_info[1]
if C_h_a_city != BG_a_city:
if C_h_a_prov == BG_a_prov:
result1.append(info)
else:
result2.append(info)
return result1, result2
‘sep’.join(seq)
def get_p_attr(com):
attr1 = get_c_label(com)
attr_list = [attr1]
attr_label = '_'.join(attr_list)
return attr_label
sep:分隔符,可以为空
seq:要链接的元素序列、字符串、元组、字典
以sep作为分隔符,将seq所有元素合并成为一个新的字符串。返回一个以分隔符sep连接各个元素后生成的字符串。
sorted()all_J_time_info1 = sorted(all_J_time_info, key=lambda x: x[1])
sort函数:对python中的列表进行排序,该函数在原空间上进行操作,对列表本身进行修改,不反回副本:
L.sort(cmp=None, key=None, reverse=False)
sorted函数比sort函数要强大许多,sorted可以对所有可迭代类型数据进行排序并返回新的已排序列表。
1.比较函数经常会用到lambda,lambda表达式通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。比如对元组组成的列表中某一项进行排序;
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key = lambda student : student[2]) #sort by age
2.比较函数经常会用到operator.itemgetter函数
operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号。
operator.itemgetter函数获取的不是值,而是定义了一个函数通过该函数作用到对象上才能获取值。
sorted函数用来排序,sorted(iterable[, cmp[, key[, reverse]]]).其中key的参数为一个函数或者lambda函数。所以itemgetter可以用来当key的参数。
a = [('join','A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key=operator.itemgetter(1,2))
3.可迭代元素经常会用到items。这是字典中的一个方法,返回由元组组成的列表。
iter()在python中iter()函数的功能是:接受一个可迭代对象,将其转换成一个迭代器。
a = [1,2,3] a_iter = iter(a) print(a_iter)
高阶用法:传入两个参数:使用常规的函数或者任意可调用对象创建迭代器。这样使用时,第一个参数必须是可调用的对象(无参数调用),用于不断调用产出值。第二个是哨符,这是标记值,当可调用对象返回这个值的时候,触发迭代器抛出的Stoplteration异常,程序结束第一个参数中的对象不断产出值,当产出的值和第二个参数是一样的时候,停止产出。
from random import randit
def d10():
return randint(1, 10)
#随机产生1~10之间的数,遇到5即停止
for i in iter(d10, 5):
print(i)



