#!/usr/bin/env python

"""
A python script to modify bib data and 
to display references with specific bibliography standard

two key features：

两大核心功能
1. bib文件抽取，bib文件内容的自定义修改
2. 格式化文献表输出，包括json，bib，text，html，bbl文件，其中bbl文件可以在tex源代码中直接使用，利用natbib宏包可以实现不同的标注样式。


"""

__author__ = "Hu zhenzhen"
__version__ = "1.0"
__license__ = "MIT"
__email__ = "hzzmail@163.com"

import string
import re
import sys
import datetime
import copy
import json
import operator



#
# 为数据map设置参数
# 选项的逻辑与biblatex基本一致，
# 差别包括:overwrite选项可以放到step步中表示
#[]=maps
#[[],[]]=map in maps
#[[[]],[]]=step in map in mpas
#[[[{optionkey: }]],[]]=step in map in mpas
#注意python正则表达方式与perl的略有不同，比如unicode表示
#python用\xHH,\uHHHH,\UHHHHHHHH表示，而perl直接用\x{HHHH}表示。
sourcemaps=[#maps
	[#map1:将ELECTRONIC类型转换为online类型
		[{"typesource":"ELECTRONIC","typetarget":"online"}]#step1
	],
	[#map2:将source域转换为url域
		[{"fieldsource":"source","fieldtarget":"url"}]#step1
	],
	[#map3:将urldate域的信息“yyyy-m-d”转换为“yyyy-mm-dd”,注意正则表达式直接写不用在外面套""
		[{"fieldsource":"urldate","match":r'(\d\d\d\d)\-(\d)\-(\d)',"replace":r'\1-0\2-0\3'}]#step1
	],
	[#map4:将urldate域的信息“yyyy-m-d”转换为“yyyy-mm-dd”,注意正则表达式直接写不用在外面套""
		[{"fieldsource":"date","match":r'(\d\d\d\d)\-(\d)\-(\d)',"replace":r'\1-0\2-0\3',"overwrite":True}]#step1
	],
	[#map5:将refdate域转换为urldate域
		[{"fieldsource":"refdate","fieldtarget":"urldate"}]#step1
	],
	[#map6:对于newspaper类型，设置note为news
		[{"pertype":"newspaper"}],#step1
		[{"fieldset":"note","fieldvalue":"news","overwrite":True}]#step2
	],
	[#map7:设置edition域等于version
		[{"fieldsource":"version","final":True}],#step1
		[{"fieldset":"edition","origfieldval":True}]#step2
	],
	[#map8:设置entrykey域设置给keywords
		[{"fieldsource":"entrykey"}],#step1
		[{"fieldset":"keywords","origfieldval":True}]#step2
	],
	[#map9:对于存在note域的情况，将其值添加到keywords
		[{"fieldsource":"note","final":True}],#step1
		[{"fieldset":"keywords","origfieldval":True,"overwrite":True,"append":True}]#step2
	],
	 [#map10:根据标题的字符编码范围确定标题的语言类型
		[{"fieldsource":"title","match":r'[\u2FF0-\u9FA5]',"final":True}],#step1
		[{"fieldset":"userd","fieldvalue":"chinese"}]#step2
	],
]

#重设新的任务处理
sourcemaps=[
	[#map1:设置entrykey域设置给keywords
		[{"fieldsource":"entrykey"}],#step1
		[{"fieldset":"keywords","origfieldval":True,"overwrite":True}]#step2
	],
]


#重设新的任务
sourcemaps=[
	[#map1:取消note域
		[{"fieldsource":"note","final":True}],#step1
		[{"fieldset":"note","null":True,"overwrite":True}]#step2
	],
	[#map2:取消abstract域
		[{"fieldsource":"abstract","final":True}],#step1
		[{"fieldset":"abstract","null":True,"overwrite":True}]#step2
	],
	[#map3:取消keywords域
		[{"fieldsource":"keywords","final":True}],#step1
		[{"fieldset":"keywords","null":True,"overwrite":True}]#step2
	],
	[#map4:取消keywords-plus域
		[{"fieldsource":"keywords-plus","final":True}],#step1
		[{"fieldset":"keywords-plus","null":True,"overwrite":True}]#step2
	],
	[#map5:取消affiliation域
		[{"fieldsource":"affiliation","final":True}],#step1
		[{"fieldset":"affiliation","null":True,"overwrite":True}]#step2
	],
	[#map6:取消funding-acknowledgement域
		[{"fieldsource":"funding-acknowledgement","final":True}],#step1
		[{"fieldset":"funding-acknowledgement","null":True,"overwrite":True}]#step2
	],
	[#map7:取消funding-text域
		[{"fieldsource":"funding-text","final":True}],#step1
		[{"fieldset":"funding-text","null":True,"overwrite":True}]#step2
	],
	]

#重设不处理
sourcemaps=[]


##------------------------------------------
## 参考文献表的制定格式设置，比如GB/T 7714-2015
## 

#全局选项
formatoptions={
"style":'authoryear',#写bbl信息的设置选项,authoryear,'numeric'
"nameformat":'uppercase',#姓名处理选项：uppercase,lowercase,given-family,family-given,pinyin
"giveninits":'space',#使用名的缩写，space表示名见用空格分隔，dotspace用点加空格，dot用点，terse无分隔，false不使用缩写
"maxbibnames":3,#
"minbibnames":3,#
"morenames":True,#
"maxbibitems":1,#
"minbibitems":1,#
"moreitems":False,#
"date":'year',#'日期处理选项'：year，iso，等
"urldate":'iso',#'日期处理选项'：year，iso，等
}

#本地化字符串
localstrings={
'andothers':{'english':'et al.','chinese':'等'},
'and':{'english':' and ','chinese':'和'},
'edition':{'english':'th ed','chinese':'版'},#th ed. 中的点不要，为方便标点处理
'in':{'english':'in: ','chinese':'见: '},
'nolocation':{'english':'[S.l.]','chinese':'[出版地不详]'},
'nopublisher':{'english':'[s.n.]','chinese':'[出版者不详]'},
'bytranslator':{'english':'trans by','chinese':'译'},
}

#标点
localpuncts={
'multinamedelim':', ',
'finalnamedelim':', ',
'andothorsdelim':', ',
'finalitemdelim':', ',
'multiitemdelim':', ',
}

#替换字符串
replacestrings={
'[出版地不详]: [出版者不详]':'[出版地不详 : 出版者不详]',
'[S.l.]: [s.n.]':'[S.l. : s.n.]',
'..':'.',
}

#类型和载体字符串
typestrings={
'book':'[M]',
'inbook':'[M]',
'standard':'[S]',
'periodical':'[J]',
'article':'[J]',
'newspaper':'[N]',
'patent':'[P]',
'online':'[EB]',
'www':'[EB]',
'electronic':'[EB]',
'proceedings':'[C]',
'inproceedings':'[C]',
'conference':'[C]',
'collection':'[G]',
'incollection':'[G]',
'thesis':'[D]',
'mastersthsis':'[D]',
'phdthesis':'[D]',
'report':'[R]',
'techreport':'[R]',
'manual':'[A]',
'archive/manual':'[A]',
'database':'[DB]',
'dataset':'[DS]',
'software':'[CP]',
'map':'[CM]',
'unpublished':'[Z]',
'misc':'[Z]',
}

#数据类型
datatypeinfo={
'namelist':['author','editor','translator','bookauthor'],
'literallist':['location','address','publisher','institution','organization','school','language','keywords'],
'literalfield':['title','journaltitle','journal','booktitle','subtitle','titleaddon','edition','version','url',
                'volume','number','endvolume','endnumber','type','note','labelnumber'],
'datefield':['date','year','urldate','enddate','origdate','eventdate'],
'rangefield':['pages']
}

#条目的著录格式
bibliographystyle={
"book":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['translator'],'options':{'nameformat':'uppercase'},'prepunct':". ",'posstring':r', \bibstring{bytranslator}'},
{"fieldsource":['edition'],'numerformat':'arabic','prepunct':". ","posstringifnumber":r'\bibstring{edition}'},
{"fieldsource":['location','address'],'prepunct':". ",'replstring':r"\bibstring{nolocation}"},
{"fieldsource":['publisher'],'prepunct':": ",'replstring':r"\bibstring{nopublisher}",'prepunctifnolastfield':'. '},
{"fieldsource":['date','year'],'prepunct':", "},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". ",'prestring':r'\url{','posstring':'}'},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"article":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['journaltitle','journal'],'prepunct':". "},
{"fieldsource":['year','date'],'prepunct':", "},
{"fieldsource":['volume'],'prepunct':", "},
{"fieldsource":['number'],'prestring':"(",'posstring':")"},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"newspaper":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['journaltitle','journal'],'prepunct':". "},
{"fieldsource":['date','year'],'prepunct':", ",'options':{'date':'iso'}},
{"fieldsource":['number'],'prestring':"(",'posstring':")"},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"inbook":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['in'],'replstring':"//",'omitifnofield':['bookauthor','editor','booktitle']},
{"fieldsource":['bookauthor','editor'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['booktitle'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':''},
{"fieldsource":['edition'],'numerformat':'arabic','prepunct':". ","posstring":r'\bibstring{edition}'},
{"fieldsource":['location','address'],'prepunct':". ",'replstring':r"\bibstring{nolocation}"},
{"fieldsource":['publisher'],'prepunct':": ",'replstring':r"\bibstring{nopublisher}",'prepunctifnolastfield':'. '},
{"fieldsource":['date','year'],'prepunct':", "},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"inproceedings":"inbook",
"incollection":"inbook",
"standard":"inbook",
"proceedings":"book",
"collection":"book",
"patent":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['number'],'prepunct':": "},
{"fieldsource":['date','year'],'prepunct':", "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"online":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['organization','instiution'],'prepunct':". "},
{"fieldsource":['date','year'],'prepunct':", ",'prepunctifnolastfield':'. ','omitifnofield':['enddate','eventdate']},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['date','enddate','eventdate'],'prepunct':". ",'options':{"date":"iso",'eventdate':'iso'},'prestring':"(","posstring":")"},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]",'prepunctifnolastfield':'. '},
{"fieldsource":['url'],'prepunct':". ",'prepunctifnolastfield':''},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"www":"online",
"electronic":"online",
"report":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['translator'],'options':{'nameformat':'uppercase'},'prepunct':". "},
{"fieldsource":['type'],'prepunct':". "},
{"fieldsource":['number'],'prepunct':"",'prepunctifnolastfield':'. '},
{"fieldsource":['version'],'prepunct':". "},
{"fieldsource":['location','address'],'prepunct':". ",'replstring':r"\bibstring{nolocation}"},
{"fieldsource":['institution','publisher'],'prepunct':": ",'replstring':r"\bibstring{nopublisher}",'prepunctifnolastfield':'. '},
{"fieldsource":['date','year'],'prepunct':", ",'omitifnofield':['location','address','institution','publisher'],'omitiffield':['url']},
{"fieldsource":['date','year'],'prepunct':". ",'prestring':'(','posstring':')','omitiffield':['location','address','institution','publisher']},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"techreport":"report",
"periodical":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['editor','author'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['year','date'],'prepunct':", "},
{"fieldsource":['volume'],'prepunct':", "},
{"fieldsource":['number'],'prestring':"(",'posstring':")-"},
{"fieldsource":['endyear','enddate'],'prepunct':", "},
{"fieldsource":['endvolume'],'prepunct':", "},
{"fieldsource":['endnumber'],'prestring':"(",'posstring':")"},
{"fieldsource":['location','address'],'prepunct':". ",'replstring':r"\bibstring{nolocation}"},
{"fieldsource":['institution','publisher'],'prepunct':": ",'replstring':r"\bibstring{nopublisher}",'prepunctifnolastfield':'. '},
{"fieldsource":['year','date'],'prepunct':", ",'posstring':'-'},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
#omitifnofield:必须所有的域都不存在才为true
#omitiffield:只要存在一个域就为true
"thesis":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['translator'],'options':{'nameformat':'uppercase'},'prepunct':". "},
{"fieldsource":['location','address'],'prepunct':". "},
{"fieldsource":['institution','publisher','school'],'prepunct':": ",'prepunctifnolastfield':'. '},
{"fieldsource":['date','year'],'prepunct':", ",'omitifnofield':['location','address','institution','publisher'],'omitiffield':['url']},
{"fieldsource":['date','year'],'prepunct':". ",'prestring':'(','posstring':')','omitiffield':['location','address','institution','publisher']},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". ",'prestring':r'\url{','posstring':'}'},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"manual":"thesis",
"unpublished":"thesis",
"database":"thesis",
"dataset":"thesis",
"software":"thesis",
"map":"thesis",
"archive":"thesis",
"misc":[
#{"fieldsource":["labelnumber"],'prestring':"[","posstring":"]","pospunct":"  "},
{"fieldsource":['author','editor','translator'],'options':{'nameformat':'uppercase'}},
{"fieldsource":['title'],'caseformat':'sentencecase','prepunct':". ",'prepunctifnolastfield':'','posstring':r"\typestring"},
{"fieldsource":['howpublished'],'prepunct':". "},
{"fieldsource":['location','address'],'prepunct':". "},
{"fieldsource":['institution','publisher'],'prepunct':": ",'prepunctifnolastfield':'. '},
{"fieldsource":['date','year'],'prepunct':", "},
{"fieldsource":['pages'],'prepunct':": "},
{"fieldsource":['urldate'],'prestring':"[","posstring":"]"},
{"fieldsource":['url'],'prepunct':". "},
{"fieldsource":['doi'],'prepunct':". "},
{"fieldsource":['endpunct'],'replstring':"."}
],
"phdthesis":"thesis",
"mastersthesis":"thesis",
}


#
#
#打印格式化后的全部文献条目文本
def printbibliography():
	
	bibliographyentries=bibliographytext.split('\n')
	
	#md文件输出,直接用write写
	mdoutfile="newformatted"+inputbibfile.replace('.bib','.md')
	fout = open(mdoutfile, 'w', encoding="utf8")
	print("INFO: writing cited references to '" + mdoutfile + "'")
	
	biblabelnumber=0
	for prtbibentry in bibliographyentries:
		if len(prtbibentry)>0:
			biblabelnumber=biblabelnumber+1
			fout.write('['+str(biblabelnumber)+'] '+prtbibentry+'\n')
	fout.close()
	
	#html文件输出,直接用write写
	mdoutfile="newformatted"+inputbibfile.replace('.bib','.html')
	fout = open(mdoutfile, 'w', encoding="utf8")
	print("INFO: writing cited references to '" + mdoutfile + "'")
	fout.write('<html><head><title>references</title></head>')
	fout.write('<body bgcolor="lightgray"><div align="top"><center>')
	fout.write('<font color="blue">')
	fout.write('<table border="0" cellPadding="10" cellSpacing="5" height="400" width="70%">')
	fout.write('<tr><td height="1" width="566" align="center" colspan="1" bgcolor="teal"></td></tr>')
	
	biblabelnumber=0
	for prtbibentry in bibliographyentries:
		if len(prtbibentry)>0:
			biblabelnumber=biblabelnumber+1
			fout.write('<tr> <td width="480" height="15" colspan="6"><font color="blue">')
			fout.write('<span style="font-family: 宋体; font-size: 14">')
			fout.write('['+str(biblabelnumber)+'] '+prtbibentry)
			fout.write('</span></font></td> </tr>')
	
	fout.write('<tr><td height="1" width="566" align="center" colspan="1" bgcolor="teal"></td></tr>')
	fout.write('</table></div></body></html>')
	fout.close()
	
	if auxfile:
		bblfile=auxfile.replace('.aux','.bbl')
	else:
		bblfile=inputbibfile.replace('.bib','.bbl')
	bbloutfile=bblfile
	fout = open(bbloutfile, 'w', encoding="utf8")
	print("INFO: writing cited references to '" + bbloutfile + "'")
	
	fout.write(r'\begin{thebibliography}{'+str(len(bibentries))+'}\n')
	
	biblabelnumber=0
	for prtbibentry in bibliographyentries:
		if len(prtbibentry)>0:
			biblabelnumber=biblabelnumber+1
			
			entrysn=0
			for bibentry in bibentries:
				entrysn=entrysn+1
				if entrysn==biblabelnumber:
					entrykeystr=bibentry['entrykey']
					entryciteauthor=formatlabelauthor(bibentry)
					entryciteyear=formatlabelyear(bibentry)
					entrycitelabel=entryciteauthor[0]+'('+entryciteyear+')'+entryciteauthor[1]
					#Baker et~al.(1995)Baker and Jackson
					break
			if formatoptions['style']=='authoryear':
				fout.write(r'\bibitem['+entrycitelabel+']{'+entrykeystr+'}'+prtbibentry+'\n')
			else:
				fout.write(r'\bibitem['+str(biblabelnumber)+']{'+entrykeystr+'}'+prtbibentry+'\n')
			
	fout.write(r'\end{thebibliography}')
	fout.close()



#
#authoryear样式提供标注标签的作者信息
#
def formatlabelauthor(bibentry):
	
	if 'author' in bibentry:
		namelist=bibentry['author']
	elif 'editor' in bibentry:
		namelist=bibentry['editor']
	elif 'translator' in bibentry:
		namelist=bibentry['translator']
	else:
		namelist='Anon'
		
	return [namelist,namelist]

#
#authoryear样式提供标注标签的年份信息
#
def formatlabelyear(bibentry):
	
	if 'year' in bibentry:
		yearlist=bibentry['year']
	elif 'eventyear' in bibentry:
		yearlist=bibentry['eventyear']
	elif 'origyear' in bibentry:
		yearlist=bibentry['origyear']
	elif 'urlyear' in bibentry:
		yearlist=bibentry['urlyear']
	else:
		yearlist='N.D.'
		
	return yearlist

#
#
#格式化全部文献条目文本
def formatallbibliography():
	labelnumber=0
	global bibliographytext
	bibliographytext=''
	for bibentry in bibentries:
		labelnumber=labelnumber+1
		bibentry['labelnumber']=labelnumber
		bibentrytext=''
		bibentrytext=formatbibentry(bibentry)
		bibliographytext=bibliographytext+bibentrytext+'\n'
		
	print('\nreferecences')
	print(bibliographytext)

#
#
#格式化一个文献条目文本
def formatbibentry(bibentry):
	
	print('--------------new entry---------')
	print('\nbibentry:',bibentry)
	#bibentrytext='entry:'
	
	#
	# 由于volume和number域可能存在范围的特殊情况，首先做特殊处理
	#
	if 'volume' in bibentry:
		if '-' in bibentry['volume']:
			multivolume=bibentry['volume'].split("-")
			bibentry['volume']=multivolume[0]
			bibentry['endvolume']=multivolume[1]
	if 'number' in bibentry:
		if '-' in bibentry['number']:
			multinumber=bibentry['number'].split("-")
			bibentry['number']=multinumber[0]
			bibentry['endnumber']=multinumber[1]
	
	#四种日期域也做范围解析
	if 'date' in bibentry:
		if '/' in bibentry['date']:
			datestring=bibentry['date'].split('/')
			bibentry['date']=datestring[0]
			bibentry['enddate']=datestring[1]
	
	if 'urldate' in bibentry:
		if '/' in bibentry['urldate']:
			datestring=bibentry['urldate'].split('/')
			bibentry['urldate']=datestring[0]
			bibentry['endurldate']=datestring[1]
	
	if 'eventdate' in bibentry:
		if '/' in bibentry['eventdate']:
			datestring=bibentry['eventdate'].split('/')
			bibentry['eventdate']=datestring[0]
			bibentry['endeventdate']=datestring[1]
	
	if 'origdate' in bibentry:
		if '/' in bibentry['origdate']:
			datestring=bibentry['origdate'].split('/')
			bibentry['origdate']=datestring[0]
			bibentry['endorigdate']=datestring[1]
	
	#
	#接着处理所有域到一个条目文本
	#
	bibentrytext=''
	
	if bibentry['entrytype'] in bibliographystyle:
		print('INFO: format style of entrytype',bibentry['entrytype'],'is defined.')
		if isinstance(bibliographystyle[bibentry['entrytype']],str):
			formattype=bibliographystyle[bibentry['entrytype']]
		else:
			formattype=bibentry['entrytype']
		
		lastfield=True #前一域存在
		
		for fieldinfo in bibliographystyle[formattype]:
			
			rtnfield=formatfield(bibentry,fieldinfo,lastfield)
			fieldtext=rtnfield[0]
			lastfield=rtnfield[1]
			
			bibentrytext=bibentrytext+fieldtext
	
	#对替换字符串做处理
	#包括对重复的标点做处理比如：..变为.
	for k,v in replacestrings.items():
		print(k,v)
		#m=re.search(k,bibentrytext)
		#print(m)
		#bibentrytext=re.sub(k,v,bibentrytext)
		#利用正则反而不行，直接用字符串替换
		bibentrytext=bibentrytext.replace(k,v)
	
	print(bibentrytext)
	return bibentrytext



#
#
#格式化文献条目的域
#不同类型的域不同处理
#分5类：姓名列表，文本列表，文本域，日期域，范围域
#其中姓名列表，文本列表，日期域，日期域，范围域，都需要进行特殊的解析
#而volume，number如果需要特殊解析则在文件域的格式处理时增加新的处理逻辑。
def formatfield(bibentry,fieldinfo,lastfield):

	print('fieldinfo:',fieldinfo)
	#首先把域的内容先解析处理
	fieldcontents=''
	
	fieldsource=None

	#首先判断域是否忽略
	fieldomit=False
	
	if 'omitifnofield' in fieldinfo and 'omitiffield' in fieldinfo:

		fieldomita=True#假设忽略的条件满足
		for field in fieldinfo['omitifnofield']:#只要需要不存在的域有一个存在，那么条件就不满足
			if field in bibentry:
				fieldomita=False
				break

		fieldomitb=False#假设忽略的条件不满足
		for field in fieldinfo['omitiffield']:#只要需要存在的域中有一个存在，那么条件就满足
			if field not in bibentry:
				fieldomitb=True
				break

		fieldomit=fieldomita and fieldomitb
		
	elif 'omitifnofield' in fieldinfo:
		
		fieldomit=True#假设忽略的条件满足
		for field in fieldinfo['omitifnofield']:#只要需要不存在的域有一个存在，那么条件就不满足
			if field in bibentry:
				fieldomit=False
				break
		
	elif 'omitiffield' in fieldinfo:
		
		fieldomit=False#假设忽略的条件不满足
		for field in fieldinfo['omitiffield']:#只要需要存在的域中有一个存在，那么条件就满足
			if field not in bibentry:
				fieldomit=True
				break
	
	print(fieldomit)
	
	
	#如果不忽略该域那么：
	if not fieldomit:
		
		#当域为姓名列表域时：
		if fieldinfo['fieldsource'][0] in  datatypeinfo['namelist']:
			#print('0',fieldinfo['fieldsource'][0])
			#print('author' in bibentry)
			for field in fieldinfo['fieldsource']:#
				#print(fieldinfo['fieldsource'])
				#print('namelist:',field)
				if field in bibentry:#当域存在域条目中时，确定要处理的域
					fieldsource=field
					break
			if fieldsource:
				#传递条目给出的一些控制选项
				if 'options' in fieldinfo:
					options=fieldinfo['options']
				else:
					options={}
				fieldcontents=namelistparser(bibentry,fieldsource,options)
			
		
		#当域为文本列表域时：
		elif fieldinfo['fieldsource'][0] in  datatypeinfo['literallist']:

			for field in fieldinfo['fieldsource']:#
				if field in bibentry:#当域存在域条目中时，确定要处理的域
					fieldsource=field
					break
			if fieldsource:
				fieldcontents=literallistparser(bibentry,fieldsource)
				
		#当域为文本域时：
		elif fieldinfo['fieldsource'][0] in  datatypeinfo['literalfield']:

			for field in fieldinfo['fieldsource']:#
				if field in bibentry:#当域存在域条目中时，确定要处理的域
					fieldsource=field
					break
			if fieldsource:
				fieldcontents=literalfieldparser(bibentry,fieldsource)
				
		
		#当域为日期域时：
		elif fieldinfo['fieldsource'][0] in  datatypeinfo['datefield']:

			for field in fieldinfo['fieldsource']:#
				if field in bibentry:#当域存在域条目中时，确定要处理的域
					fieldsource=field
					break
			if fieldsource:
				#传递条目给出的一些控制选项
				if 'options' in fieldinfo:
					options=fieldinfo['options']
				else:
					options={}
				fieldcontents=datefieldparser(bibentry,fieldsource,options)
				
				
		#当域为范围域时：
		elif fieldinfo['fieldsource'][0] in  datatypeinfo['rangefield']:

			for field in fieldinfo['fieldsource']:#
				if field in bibentry:#当域存在域条目中时，确定要处理的域
					fieldsource=field
					break
			if fieldsource:
				fieldcontents=rangefieldparser(bibentry,fieldsource)
	
	if not fieldsource:
		if 'replstring' in fieldinfo and fieldinfo['replstring']:
			print('replstring')
			fieldsource=True
			fieldcontents=fieldinfo['replstring']
			
	
	#接着做进一步的格式化，包括标点，格式，字体等
	fieldtext=''
	
	print(fieldsource)
	if fieldsource:
		if lastfield:#当前一个著录项存在，则正常输出
			if 'prepunct' in fieldinfo:
				fieldtext=fieldtext+fieldinfo['prepunct']
		else:#当前一个著录项不存在，则首先输出'prepunctifnolastfield'
			if 'prepunctifnolastfield' in fieldinfo:
				fieldtext=fieldtext+fieldinfo['prepunctifnolastfield']
			elif 'prepunct' in fieldinfo:
				fieldtext=fieldtext+fieldinfo['prepunct']
		
		if 'prestring' in fieldinfo:
			fieldtext=fieldtext+fieldinfo['prestring']
		
		if 'fieldformat' in fieldinfo:
			fieldtext=fieldtext+'{'+fieldinfo['fieldformat']+'{'+fieldcontents+'}}'
		else:
			fieldtext=fieldtext+str(fieldcontents)
		
		if 'posstring' in fieldinfo:
			fieldtext=fieldtext+fieldinfo['posstring']
			
		if 'posstringifnumber' in fieldinfo:
			try:
				numtemp=int(fieldcontents)
				if  isinstance(numtemp,int):
					fieldtext=fieldtext+fieldinfo['posstringifnumber']
			except:
				print('info:waring the field value can not convert to integer')
		
		if 'pospunct' in fieldinfo:
			fieldtext=fieldtext+fieldinfo['pospunct']
			
		#更新lastfiled
		lastfield=True
	else:
		lastfield=False
	
	
	#自定义标点的处理
	print('fieldtext:',fieldtext)
	while r'\printdelim' in fieldtext:
		
		m = re.search(r'\\printdelim{([^\}]*)}',fieldtext)#注意贪婪算法的影响，所以要排除\}字符
		print('m.group(1):',m.group(1))
		fieldtext=re.sub(r'\\printdelim{[^\}]*}',localpuncts[m.group(1)],fieldtext,count=1)
		print('fieldtext:',fieldtext)
	
	
	#本地化字符串的处理
	print('fieldtext:',fieldtext)
	while r'\bibstring' in fieldtext:
		
		language=languagejudgement(bibentry,fieldinfo,fieldsource)
		m = re.search(r'\\bibstring{([^\}]*)}',fieldtext)#注意\字符的匹配，即便是在r''中也需要用\\表示
		fieldtext=re.sub(r'\\bibstring{[^\}]*}',localstrings[m.group(1)][language],fieldtext,count=1)
		print('fieldtext:',fieldtext)
		#下面这句不行因为，在字典取值是，不支持\1这样的正则表达式
		#fieldtext=re.sub(r'\\bibstring{(.*)}',localstrings[r'\1'][language],fieldtext,count=1)
	
	#标题的类型和载体标识符的处理
	if r'\typestring' in fieldtext:#当需要处理类型和载体时
		if bibentry['entrytype'] in typestrings:#当条目对应的类型存在时
			print(r'\typestring in',fieldtext)
			typestring=typestrings[bibentry['entrytype']]
			if 'url' in bibentry:
				typestring=typestring.replace(']','/OL]')
			elif 'medium' in bibentry:
				rplctypestring=bibentry['medium']+']'
				typestring=typestring.replace(']',rplctypestring)
		else:#当条目对应的类型不存在时，当做其它类型处理
			typestring='[Z]'

		print(typestring)
		fieldtext=fieldtext.replace(r'\typestring',typestring)
		
	return [fieldtext,lastfield]





#
#根据作者域或者标题域确定条目的语言
#
def languagejudgement(bibentry,fieldinfo,fieldsource):

	if fieldsource in datatypeinfo['namelist']:#当域是作者类时，利用作者域本身信息做判断
	
		language=fieldlanguage(bibentry[fieldsource])
		
	else:#其它情况，利用title域做判断
		if 'title' in bibentry:
			language=fieldlanguage(bibentry['title'])
		elif 'author' in bibentry:
			language=fieldlanguage(bibentry['author'])
		else:
			language='english'
		
	return language
	

#
#根据域值所在的字符范围确定域的语言
#
def fieldlanguage(fieldvalueinfo):

	if re.match(r'[\u2FF0-\u9FA5]', fieldvalueinfo):
		language='chinese'
	elif re.match(r'[\u3040-\u30FF\u31F0}-\u31FF]', fieldvalueinfo):
		language='japanese'
	elif re.match(r'[\u1100-\u11FF\u3130-\u318F\uAC00-\uD7AF]', fieldvalueinfo):
		language='korean'
	elif re.match(r'[\u0400-\u052F]', fieldvalueinfo):
		language='russian'
	elif re.match(r'[\u0100-\u017F]', fieldvalueinfo):
		language='french'
	else:
		language='english'
	
	return language


#
#
#对存在{}做保护的字符串进行分割
def safetysplit(strtosplt,seps):
	
	#首先查找{}保护的所有字符串
	s1=re.findall('\{.*?\}',strtosplt)
	
	#接着确定保护字符串中是否存在分割用字符串
	sepinbrace=False
	for s1a in s1:
		for sep in seps:
			if sep in s1a:
				sepinbrace=True
				break
		if sepinbrace:
			break
	#print(sepinbrace)
			
	#若保护字符串中存在分割字符串那么做特殊处理		
	a=strtosplt
	if sepinbrace:
		
		#保护字符串用特殊字符串代替，特殊字符串与分割字符串没有任何关联
		strsn=0
		for stra1 in s1:
			strsn=strsn+1
			a=a.replace(stra1,'$'+str(strsn)+'$')
		#print(a)
		
		#处理原字符串为只需要一个分隔字符串就能分隔
		if len(seps)>1:
			for i in range(1,len(seps)):
				a=a.replace(seps[i],seps[0])
			#print(a)
		
		#接着做分割
		names=a.split(seps[0])
		#print(names)
		
		#对分割后的字符串做还原，即把特殊字符串还原回保护字符串
		namesnew=[]
		for name in names:
			strsn=0
			for stra1 in s1:
				strsn=strsn+1
				name=name.replace('$'+str(strsn)+'$',stra1)
			#print(name)
			namesnew.append(name.strip().lstrip())
		
	else:
		#处理原字符串为只需要一个分隔字符串就能分隔
		if len(seps)>1:
			for i in range(1,len(seps)):
				a=a.replace(seps[i],seps[0])
			#print(a)
		
		#直接分割
		names=a.split(seps[0])
		namesnew=[]
		for name in names:
			namesnew.append(name.strip().lstrip())
		
	#print(namesnew)
	return namesnew

#
#
#姓名列表解析
#增加条目给出的选项
def namelistparser(bibentry,fieldsource,options):
	fieldcontents=bibentry[fieldsource]
	
	#首先做针对{}保护的处理
	#{}有可能保护一部分，有可能保护全部
	#首先判断{}是否存在，若存在，那么可以确定需要做保护处理，否则用常规处理
	#当然这些事情可以在一个函数中处理

	#首先姓名列表进行分解，包括用' and '和' AND '做分解
	#利用safetysplit函数实现安全的分解
	seps=[' and ',' AND ']
	fieldcontents=fieldcontents.lstrip().strip()
	fieldauthors=safetysplit(fieldcontents,seps)

	print('fieldauthors:',fieldauthors)
	#接着从各个姓名得到更详细的分解信息
	fieldnames=[]
	for name in fieldauthors:
		if name.lower() == 'others':
			nameinfo={'morename':True}
		else:
			if fieldlanguage(name)=='chinese':#当中文姓名中存在逗号先去除
				if ', ' in name:
					name=name.replace(', ','')
			else:
				pass
			nameinfo=singlenameparser(name)
		fieldnames.append(nameinfo)
	
	#最后根据全局和局部选项进行格式化
	nameformattedstr=''
	
	#根据'maxbibnames'和'minbibnames'截短
	if 'maxbibnames' in options:#首先使用条目中的选项
		if len(fieldnames)>options['maxbibnames']:
			fieldnamestrunc=fieldnames[:options['minbibnames']]
			nameinfo={'morename':True}
			fieldnamestrunc.append(nameinfo)
		else:
			fieldnamestrunc=fieldnames
	elif 'maxbibnames' in formatoptions:#接着使用全局选项
		if len(fieldnames)>formatoptions['maxbibnames']:
			fieldnamestrunc=fieldnames[:formatoptions['minbibnames']]
			nameinfo={'morename':True}
			fieldnamestrunc.append(nameinfo)
		else:
			fieldnamestrunc=fieldnames
	else:
		fieldnamestrunc=fieldnames
	
	#当条目选择中存在'nameformat'
	if 'nameformat' in options:
		option={'nameformat':options['nameformat']}
	else:
		option={}
	
	print('fieldnamestrunc:',fieldnamestrunc)
	nameliststop=len(fieldnamestrunc)
	nameliststart=1
	namelistcount=0
	for nameinfo in fieldnamestrunc:
		namelistcount=namelistcount+1
		if 'morename' in nameinfo:
			if formatoptions['morenames']:#只有设置morenames为true是才输出other的相关信息
				nameformattedstr=nameformattedstr+r'\printdelim{andothorsdelim}\bibstring{andothers}'
		else:
			if namelistcount==nameliststop and namelistcount>1:#当没有others时最后一个姓名前加的标点
				nameformattedstr=nameformattedstr+r'\printdelim{finalnamedelim}'+singlenameformat(nameinfo,option)
			elif namelistcount==nameliststart:
				nameformattedstr=singlenameformat(nameinfo,option)
			else:
				nameformattedstr=nameformattedstr+r'\printdelim{multinamedelim}'+singlenameformat(nameinfo,option)
	
	return nameformattedstr


#
#
#单个姓名格式化
def singlenameformat(nameinfo,option):
	
	singlenamefmtstr=''
	
	
	if 'nameformat' in option:#首先使用条目给出的选项
		nameformat=option['nameformat']
	elif 'nameformat' in formatoptions:#接着使用全局的选项
		nameformat=formatoptions['nameformat']
	else:#最后使用默认的选项
		nameformat='uppercase'
	
	
	#根据单个姓名格式化选项来实现具体的格式
	if nameformat=='uppercase':
		
		if nameinfo['family'].startswith('{'):
			singlenamefmtstr=nameinfo['family']
		else:
			singlenamefmtstr=nameinfo['family'].upper()
		
		#根据选项确定使用名的缩写
		if formatoptions["giveninits"]=='space':#space表示名见用空格分隔，
			if 'given' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['giveni'].upper()
			if 'middle' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['middlei'].upper()
		elif formatoptions["giveninits"]=='dotspace':#dotspace用点加空格，
			if 'given' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['giveni'].upper()
			if 'middle' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+'. '+nameinfo['middlei'].upper()+'.'
		elif formatoptions["giveninits"]=='dot':#dot用点，
			if 'given' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['giveni'].upper()
			if 'middle' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+'.'+nameinfo['middlei'].upper()+'.'
		elif formatoptions["giveninits"]=='terse':#terse无分隔，
			if 'given' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['giveni'].upper()
			if 'middle' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+nameinfo['middlei'].upper()
		elif formatoptions["giveninits"]=='false':#false不使用缩写
			if 'given' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['given'].upper()
			if 'middle' in nameinfo:
				singlenamefmtstr=singlenamefmtstr+' '+nameinfo['middle'].upper()

		
	elif nameformat=='lowercase':
		pass
	elif nameformat=='given-family':
		pass
	elif nameformat=='family-given':
		pass
	elif nameformat=='pinyin':
		pass
	else:
		pass
	
	return singlenamefmtstr


#
#
#单个姓名解析
def singlenameparser(name):
	
	singlename=name
	
	print('name:',name)
	
	#字典用于存储所有的姓名成分信息
	namepartsinfo={}
	
	nameparts=safetysplit(singlename,[','])
	
	if len(nameparts)==3:#两个逗号的情况，表示存在family和suffix
		
		prefixfamily=safetysplit(nameparts[0].lstrip().strip(),[' '])
		if len(prefixfamily)>1:
			namepartsinfo['prefix']=prefixfamily[0].lstrip().strip()
			namepartsinfo['family']=prefixfamily[1].lstrip().strip()
		else:
			namepartsinfo['family']=prefixfamily[0].lstrip().strip()
			
		namepartsinfo['suffix']=nameparts[1].lstrip().strip()
		
		
		givenmiddle=safetysplit(nameparts[2].lstrip().strip(),[' '])
		if len(givenmiddle)>1:
			namepartsinfo['given']=givenmiddle[0].lstrip().strip()
			namepartsinfo['middle']=givenmiddle[1].lstrip().strip()
		else:
			namepartsinfo['given']=givenmiddle[0].lstrip().strip()
		
	elif len(nameparts)==2:
		
		prefixfamily=safetysplit(nameparts[0].lstrip().strip(),[' '])
		if len(prefixfamily)>1:
			namepartsinfo['prefix']=prefixfamily[0].lstrip().strip()
			namepartsinfo['family']=prefixfamily[1].lstrip().strip()
		else:
			namepartsinfo['family']=prefixfamily[0].lstrip().strip()
			
		
		givenmiddle=safetysplit(nameparts[1].lstrip().strip(),[' '])
		if len(givenmiddle)>1:
			namepartsinfo['given']=givenmiddle[0].lstrip().strip()
			namepartsinfo['middle']=givenmiddle[1].lstrip().strip()
		else:
			namepartsinfo['given']=givenmiddle[0].lstrip().strip()
		
	else:
		givenmiddlefamily=safetysplit(nameparts[0].lstrip().strip(),[' '])
		if len(givenmiddlefamily)==3:
			namepartsinfo['given']=givenmiddlefamily[0].lstrip().strip()
			namepartsinfo['middle']=givenmiddlefamily[1].lstrip().strip()
			namepartsinfo['family']=givenmiddlefamily[2].lstrip().strip()
		elif len(givenmiddlefamily)==2:
			namepartsinfo['given']=givenmiddlefamily[0].lstrip().strip()
			namepartsinfo['family']=givenmiddlefamily[1].lstrip().strip()
		elif len(givenmiddlefamily)==1:
			namepartsinfo['family']=givenmiddlefamily[0].lstrip().strip()
	
	
	print('nameparts:',namepartsinfo)
	
	if 'family' in namepartsinfo:
		if namepartsinfo['family'].startswith('{'):
			namepartsinfo['familyi']=namepartsinfo['family']
		else:
			namepartsinfo['familyi']=namepartsinfo['family'][0].upper()
	
	if 'given' in namepartsinfo:
		#print(namepartsinfo['given'])
		if namepartsinfo['given'].startswith('{'):
			namepartsinfo['giveni']=namepartsinfo['given']
		else:
			namepartsinfo['giveni']=namepartsinfo['given'][0].upper()
		
	if 'middle' in namepartsinfo:
		if namepartsinfo['middle'].startswith('{'):
			namepartsinfo['middle']=namepartsinfo['middle']
		else:
			namepartsinfo['middlei']=namepartsinfo['middle'][0].upper()
		
	return namepartsinfo

#
#
#文本列表解析
def literallistparser(bibentry,fieldsource):
	fieldcontents=bibentry[fieldsource]
	
	
	#首先从文本列表分解出各个项，包括用' and '和' AND '做分解
	#利用safetysplit函数实现安全的分解
	seps=[' and ',' AND ']
	fieldcontents=fieldcontents.lstrip().strip()
	fielditems=safetysplit(fieldcontents,seps)
	
	print('fielditems:',fielditems)
	
	#根据'maxbibitems'和'minbibitems'截短
	fielditemstrunc=[]
	
	if len(fielditems)>formatoptions['maxbibitems']:
		fielditemstrunc=fielditems[:formatoptions['minbibitems']]
		fielditemstrunc.append('others')
	else:
		fielditemstrunc=fielditems
	
	#重设一下others的大小写，因为可能输入的时大写的
	if fielditems[-1].lower() == 'others':
		fielditems[-1]='others'
	
	#最后根据全局和局部选项进行格式化
	itemliststop=len(fielditemstrunc)
	itemliststart=1
	itemlistcount=0
	itemformattedstr=''
	for iteminfo in fielditemstrunc:
		itemlistcount=itemlistcount+1
		if iteminfo == 'others':
			if formatoptions['moreitems']:#只有设置moreitems为true是才输出other的相关信息
				itemformattedstr=itemformattedstr+r'\printdelim{andothorsdelim}\bibstring{andothers}'
		else:
			if itemlistcount==itemliststop and itemlistcount>1:#当没有others时最后一个项前加标点
				itemformattedstr=itemformattedstr+r'\printdelim{finalitemdelim}'+iteminfo
			elif itemlistcount==itemliststart:
				itemformattedstr=iteminfo
			else:
				itemformattedstr=itemformattedstr+r'\printdelim{multiitemdelim}'+iteminfo
	
	return itemformattedstr

#
#
#文本域解析
def literalfieldparser(bibentry,fieldsource):
	fieldcontents=bibentry[fieldsource]
	
	return fieldcontents

#
#
#日期域解析
#条目设置的选项options:
def datefieldparser(bibentry,fieldsource,options):
	fieldcontents=bibentry[fieldsource]
	
	#首先从日期域，解析日期类型：
	dateparts={}
	if fieldsource=='year':
		datestring=bibentry[fieldsource]
		datetype=''
	else:
		datetype=fieldsource.replace('date','')
		datestring=bibentry[fieldsource]
		
		
	#日期的年月日解析
	#日期一般很少用{}进行保护，当保护的时候通常是整个进行包括，所以通常{}会出现在域的起始和末尾
	#所以当出现{字符时通常不用再做解析
	if '{' in datestring:
		datepartinfo=[datestring]
	else:
		datepartinfo=datestring.split('-')
	
	if len(datepartinfo)==3:
		dateparts[datetype+'year']=datepartinfo[0].strip().lstrip()
		dateparts[datetype+'month']=datepartinfo[1].strip().lstrip()
		dateparts[datetype+'day']=datepartinfo[2].strip().lstrip()
	elif len(datepartinfo)==2:
		dateparts[datetype+'year']=datepartinfo[0].strip().lstrip()
		dateparts[datetype+'month']=datepartinfo[1].strip().lstrip()
	else:
		dateparts[datetype+'year']=datepartinfo[0].strip().lstrip()
	
	print(dateparts)
	
	#判断解析的年月日是不是整数，若不是则表示日期不可解析
	datecanbeparse=True
	for k,v in dateparts.items():
		try:
			datepartisint=isinstance(int(v),int)
		except:
			print('INFO: WARNING'+fieldsource+'can not be parsed')
			datecanbeparse=False
			break
		
	
	#然后根据全局选项进行格式化：
	#如果解析的年月日不是整数，那么对于date域则忽略，对于year域则直接输出
	if datecanbeparse:
		if datetype+'date' in options:#首先使用条目给出的选项
			fieldcontents=singledateformat(dateparts,datetype,options[datetype+'date'])
		elif datetype+'date' in formatoptions:#接着使用全局给出的选项
			fieldcontents=singledateformat(dateparts,datetype,formatoptions[datetype+'date'])
		else:#否则使用默认选项
			fieldcontents=singledateformat(dateparts,datetype,'default')
	else:
		if fieldsource=='year':
			fieldcontents=bibentry[fieldsource]
		else:
			fieldcontents=''
			
	return fieldcontents


#
#
# 根据日期的设置选项格式化单个日期
def singledateformat(dateparts,datetype,formatoption):
	if formatoption=='year':
		dateformatstr=dateparts[datetype+'year']
	elif formatoption=='iso':
		dateformatstr=dateparts[datetype+'year']
		if len(dateparts[datetype+'month'])<2:
			dateformatstr=dateformatstr+'-0'+dateparts[datetype+'month']
		else:
			dateformatstr=dateformatstr+'-'+dateparts[datetype+'month']
		if len(dateparts[datetype+'day'])<2:
			dateformatstr=dateformatstr+'-0'+dateparts[datetype+'day']
		else:
			dateformatstr=dateformatstr+'-'+dateparts[datetype+'day']
	elif formatoption=='ymd':
		dateformatstr=dateparts[datetype+'year']
		dateformatstr=dateformatstr+'-'+dateparts[datetype+'month']
		dateformatstr=dateformatstr+'-'+dateparts[datetype+'day']
	elif formatoption=='default':
		dateformatstr=dateparts[datetype+'year']
	else:
		pass
	
	return dateformatstr





#
#
#范围域解析
def rangefieldparser(bibentry,fieldsource):
	fieldcontents=bibentry[fieldsource]
	
	return fieldcontents


#
#
#打开bib文件
def readfilecontents(bibFile):
	print("INFO: Reading references from '" + bibFile + "'")
	try:
		fIn = open(bibFile, 'r', encoding="utf8")
		global bibfilecontents
		bibfilecontents=fIn.readlines()
		fIn.close()
		
		global usedIds
		usedIds = set()
		if auxfile:
			fInAux = open(auxfile, 'r', encoding="utf8")
			for line in fInAux:
				if line.startswith("\\citation") or line.startswith("\\abx@aux@cite"):
					ids = line.split("{")[1].rstrip("} \n").split(", ")
					for id in ids:
						if (id != ""):
							usedIds.add(id)
			fInAux.close()
			print('references:',usedIds)
		
	except IOError:
		print("ERROR: Input bib file '" + bibFile +
				"' doesn't exist or is not readable")
		sys.exit(-1)

#
#打印bib文件内容
def printfilecontents():
	for line in bibfilecontents:
		print(line)



#
#输出修改后的bib文件
def writefilenewbib(bibFile):

	print(datetime.datetime.now().isoformat(timespec='seconds'))
	
	#json文件输出,用dump方法
	jsonoutfile="new"+bibFile.replace('.bib','.json')
	print("INFO: writing all references to '" + jsonoutfile + "'")
	fout = open(jsonoutfile, 'w', encoding="utf8")
	json.dump(bibentries, fout)
	fout.close()
	
	#json文件输出,直接用write写
	jsonoutfile="new"+bibFile.replace('.bib','cited.json')
	fout = open(jsonoutfile, 'w', encoding="utf8")
	print("INFO: writing cited references to '" + jsonoutfile + "'")
	fout.write('[\n')
	for bibentry in bibentries:
		if bibentry["entrykey"] in usedIds or not usedIds:
			fout.write(repr(bibentry)+',\n')
	fout.write(']\n')
	fout.close()

	#bib文件输出
	biboutfile="new"+bibFile
	
	try:
		fout = open(biboutfile, 'w', encoding="utf8")
		fout.write("%% \n")
		fout.write("%% bib file modified by biblatex-map.py\n")
		
		fout.write("%% "+datetime.datetime.now().isoformat(timespec='seconds')+"\n")
		fout.write("%% \n\n\n")
		
		for bibcomment in bibcomments:
			for k,v in bibcomment.items():
				if k=="entrytype":
					fout.write('@'+bibcomment["entrytype"]+'{')
				else:
					fout.write(str(v))
			fout.write('}\n\n')
			
		for bibstring in bibstrings:
			for k,v in bibstring.items():
				if k=="entrytype":
					fout.write('@'+bibstring["entrytype"]+'{')
				else:
					fout.write(str(v))
			fout.write('}\n\n')
		
		writebibentrycounter=0
		if auxfile:
			print("INFO: writing cited references in aux to '" + biboutfile + "'")
			
			for bibentry in bibentries:
				if bibentry["entrykey"] in usedIds:
					writebibentrycounter=writebibentrycounter+1
					fout.write('@'+bibentry["entrytype"]+'{'+bibentry["entrykey"]+',\n')
					for k,v in bibentry.items():
						if k=="entrytype" or k=="entrykey" or v=='""' or v==None or k=='entrysn':
							pass
						else:
							fout.write('\t'+str(k)+' = {'+str(v)+'},\n')
					fout.write('}\n\n')
		else:
			print("INFO: writing all references to '" + biboutfile + "'")
			for bibentry in bibentries:
				writebibentrycounter=writebibentrycounter+1
				fout.write('@'+bibentry["entrytype"]+'{'+bibentry["entrykey"]+',\n')
				for k,v in bibentry.items():
					if k=="entrytype" or k=="entrykey" or v=='""' or k=='entrysn' or v==None:
						pass
					else:
						fout.write('\t'+k+' = {'+v+'},\n')
				fout.write('}\n\n')
		
		fout.close()
		print("INFO: " + str(writebibentrycounter) + " references writed")
	except IOError:
		print("ERROR: Input bib file '" + bibFile +
				"' doesn't exist or is not readable")
		sys.exit(-1)
		



#
#将条目解析放到bibentries列表中
#每个条目是一个dict字典
def bibentryparsing():
	global bibentries
	global bibcomments
	global bibstrings
	bibentries=[]#用于记录所有条目
	bibentry={}#用于记录当前条目
	
	bibcomments=[]#用于记录所有@comment条目
	bibcomment={}#用于记录当前@comment条目
	
	bibstrings=[]#用于记录所有@stirng条目
	bibstring={}#用于记录当前@stirng条目
	
	entrysn=0 #用于标记条目序号
	bibentrycounter=0##用于标记条目总数
	commentsn=0 #用于标记@comment条目序号
	bibcommentcounter=0#用于标记@comment条目总数
	stringsn=0 #用于标记@stirng条目序号
	bibstringcounter=0#用于标记@stirng条目总数
	
	entrystated=False #用于标记条目开始
	fieldvalended=True #用于标记域的值当前行是否已经结束
	fieldvalue="" #用于记录当前域的值
	counterbracket=0 #用于追踪{}符号
	counterquotes=0  #用于追踪“”符号
	enclosebracket=True #用于记录是用{}还是用“”做为域的值的包围符号
	enclosenone=False #用于记录域的值无包围符号的情况
	
	for line in bibfilecontents:#遍历所有行
		#print(line)
		
		if line.startswith("@") and not "@comment" in line.lower() and not "@string" in line.lower():#判断条目开始行
			entrysn=entrysn+1
			entrystated=True #新条目开始
			print('entrysn=',entrysn)
			entrynow=line.lstrip('@').split(sep='{', maxsplit=1)
			#print(entrynow)
			entrytype=entrynow[0]
			bibentry['entrytype']=entrytype.lower()#条目类型小写，方便比较
			entrykey=entrynow[1].split(sep=',', maxsplit=1)[0]
			bibentry['entrykey']=entrykey
			bibentry['entrysn']=entrysn
		elif entrystated: #只有新条目开始了才有意义

			if fieldvalended: #当前行不是前面的未结束域的值
				if '=' in line and not line.lstrip().startswith("}"):
					#排除以'}'开头的行后根据=号判断条目域信息行，不可能出现=号无法判断信息行的问题，
					#因为是域值中存在=的特殊情况已经在未结束逻辑处理
					entryline=line.lstrip()
					entrynow=entryline.split(sep='=', maxsplit=1)
					#print(entrynow)
					entryfield=entrynow[0].strip().lstrip().lower()#域名小写，方便比较
					entryfieldline=entrynow[1].lstrip()
					
					if entryfieldline.startswith("{"):
						enclosebracket=True
					elif entryfieldline.startswith('"'):
						enclosebracket=False
					else:#当没有符号包围是设置enclosenone以便特殊处理
						enclosenone=True
					
					fieldvalcontinued=True #临时标记，用于记录域值是否还未结束，先假设未结束
					for chari in entryfieldline.strip():#遍历域值中的每个字符
						fieldvalue=fieldvalue+chari
						if chari =='{':#对{符号进行追踪
							counterbracket=counterbracket+1
						elif chari =='}':#对}符号进行追踪
							counterbracket=counterbracket-1
							if enclosebracket:
								if counterbracket==0:#当}与域开始的{配对，那么说明域值已经结束
									bibentry[entryfield]=fieldvalue[1:-1]#利用strip可能会消多次，因此用list的方式处理
									fieldvalue=""
									counterbracket=0
									counterquotes=0
									fieldvalended=True
									fieldvalcontinued=False
									break #直接跳出循环
						elif chari =='"':
							counterquotes=counterquotes+1
							if not enclosebracket:
								if operator.mod(counterquotes,2)==0:
									bibentry[entryfield]=fieldvalue[1:-1]
									fieldvalue=""
									counterbracket=0
									counterquotes=0
									fieldvalended=True
									fieldvalcontinued=False
									break
						elif chari ==',':#若域值没有包围符号那么遇到,号即为域值结束
							if enclosenone:
								bibentry[entryfield]=fieldvalue[:-1]
								fieldvalue=""
								counterbracket=0
								counterquotes=0
								fieldvalended=True
								fieldvalcontinued=False
								enclosenone=False
						
						#测试：输出看是否正确
						#if entryfield=='abstract':
						#	print('val=',fieldvalue)
						#	print('counterbracket=',counterbracket)
						
					if fieldvalcontinued:
						fieldvalended=False
				
				elif '}' in line:#条目结束行

					#global bibentryglobal
					#bibentryglobal=copy.deepcopy(bibentry) 
					#print('entry:',bibentryglobal)
					#bibentries.append(bibentryglobal)
					print('entry:',bibentry)
					bibentries.append(bibentry)
					bibentry={}
					entrystated=False
					
			else: #当前行是前面的未结束域的值，因此直接往前面的域值添加即可
				fieldvalcontinued=True

				entryfieldline=line
				
				if enclosenone:#当域没有包围符号时，接续的行可能是用逗号结束的域，也可能没有逗号，而用}直接结束条目信息
					for chari in entryfieldline.strip():
						fieldvalue=fieldvalue+chari
						if chari ==',':
							bibentry[entryfield]=fieldvalue[:-1]
							fieldvalue=""
							counterbracket=0
							counterquotes=0
							fieldvalended=True
							fieldvalcontinued=False
							enclosenone=False
						elif chari =='}':
							bibentry[entryfield]=fieldvalue[:-1]
							fieldvalue=""
							counterbracket=0
							counterquotes=0
							fieldvalended=True
							fieldvalcontinued=False
							enclosenone=False
							print('entry:',bibentry)
							bibentries.append(bibentry)
							bibentry={}
							entrystated=False
				
				else:
					for chari in entryfieldline.strip():
						fieldvalue=fieldvalue+chari
						if chari =='{':
							counterbracket=counterbracket+1
						elif chari =='}':
							counterbracket=counterbracket-1
							if enclosebracket:
								if counterbracket==0:
									bibentry[entryfield]=fieldvalue[1:-1]
									fieldvalue=""
									counterbracket=0
									counterquotes=0
									fieldvalended=True
									fieldvalcontinued=False
									break
						elif chari =='"':
							counterquotes=counterquotes+1
							if not enclosebracket:
								if mod(counterquotes,2)==0:
									bibentry[entryfield]=fieldvalue[1:-1]
									fieldvalue=""
									counterbracket=0
									counterquotes=0
									fieldvalended=True
									fieldvalcontinued=False
									break

								
				if fieldvalcontinued:
					fieldvalended=False
		elif line.startswith("@") and "@comment" in line.lower():#@comment的起始
			commentsn=commentsn+1
			entrynow=line.lstrip('@').split(sep='{', maxsplit=1)
			entrytype=entrynow[0]
			bibcomment['entrytype']=entrytype.lower()#条目类型小写，方便比较
			entrycontents=entrynow[1].strip()[:-1]
			bibcomment['entrycontents']=entrycontents
			print(bibcomment)
			bibcomments.append(bibcomment)
			bibcomment={}
			
		elif line.startswith("@") and "@string" in line.lower():#@string的起始
			stringsn=stringsn+1
			entrynow=line.lstrip('@').split(sep='{', maxsplit=1)
			entrytype=entrynow[0]
			bibstring['entrytype']=entrytype.lower()#条目类型小写，方便比较
			entrycontents=entrynow[1].strip()[:-1]
			bibstring['entrycontents']=entrycontents
			print(bibstring)
			bibstrings.append(bibstring)
			bibstring={}

	
	bibentrycounter=len(bibentries)
	bibcommentcounter=len(bibcomments)
	bibstringcounter=len(bibstrings)
	print('entrysn=',entrysn,' commentsn=',commentsn,' stringsn=',stringsn)
	print('entryct=',bibentrycounter,' commentct=',bibcommentcounter,' stringct=',bibstringcounter)
	
	if not bibentrycounter==entrysn or not bibcommentcounter==commentsn or not bibstringcounter==stringsn:
		try:
			raise BibParsingError('bib file parsing went wrong!')
		except BibParsingError as e:
			raise BibParsingError(e.message)
	print('entrytotal=',bibentrycounter)
	
	#输出解析后的bib文件信息
	#for bibentryi in bibentries:
		#print(bibentryi)


#
#打印bibentries列表中的所有条目
def printbibentries():
	for bibentryi in bibentries:
		print(bibentryi)	
			

#
#自定义异常类
class BibParsingError(Exception):
	def __init__(self,message):
		Exception.__init__(self)
		self.message=message 
		
#
# 执行数据映射操作
# 还有很多选项没有实现，20190209
# 实现的选项中也需要和未实现的选项进行数据传递
def execsourcemap():
	for map in sourcemaps:#every map in maps，每个map逐步开始
		for bibentry in bibentries:#每个映射都需要遍历所有条目，对每个条目做map
	
			mapcontinue=1#大于0表示正常，继续当前条目的map
			typesrcinfo={}#用于记录typesource相关处理结果
			fieldsrcinfo={}#用于记录fieldsource相关处理的结果
			constraintinfo={}#用于记录类型等限制信息记录
			constraintinfo['pertype']=[]
			constraintinfo['pernottype']=[]
			
			#print("map info=",map)
			for step in map:#every step in map
				if mapcontinue>0:#对前面已经final完成的情况做限制
					for keyvals in step:#key-vals in step
						for k,v in keyvals.items():#step 是有迹可循的，每个step总是存在一些东西，找到这些做其中的逻辑即可
							#print(k,v)
							
							if k=="typesource":#条目类型设置
								mapcontinue=maptypesource(keyvals,bibentry,typesrcinfo)#coef is dict
								
							elif k=="fieldsource":#域查找或设置
								mapcontinue=mapfieldsource(keyvals,bibentry,fieldsrcinfo,constraintinfo)#
								#print("fieldsource step:",fieldsrcinfo)
								
							elif k=="fieldset":#域设置
								mapcontinue=mapfieldset(keyvals,bibentry,typesrcinfo,fieldsrcinfo,constraintinfo)#
								
							elif k=="pertype": #类型限制
								mapcontinue=mappertype(keyvals,constraintinfo)
								
							elif k=="pernottype":#类型限制
								mapcontinue=mappernottype(keyvals,constraintinfo)
								
							elif k=="notfield":#域限制
								mapcontinue=mapnotfield(keyvals,bibentry,fieldsrcinfo,constraintinfo)#
							else:
								pass

								
#
#域限制,若域确定不存在则终止map				
def mapnotfield(keyvals,bibentry,fieldsrcinfo,constraintinfo):

	setcontinue=True
	print(setcontinue)
	if len(constraintinfo['pertype'])>0:
		if bibentry['entrytype'] not in constraintinfo['pertype']:#
			setcontinue=False
	if len(constraintinfo['pernottype'])>0:
		if bibentry['entrytype'] in constraintinfo['pernottype']:#
			setcontinue=False
	print(setcontinue)

	
	print("constraints:notfield")
	if setcontinue:
		for k,v in keyvals.items():
			#print(k,v)
			if k=='notfield':
				notfield=v.lower()
			elif k=='final':
				fieldfinal=v
			else:
				pass
				
		if notfield not in bibentry:#当notfield不存在，则判断为true，若存在final则终止，否则继续
			if fieldfinal:
				return 0
			else:
				return 1
		else:
			return 1
			
	else:
		return 0
	

								
								#
#条目类型限制,将类型限制信息放入字典				
def mappertype(keyvals,constraintinfo):
	
	print("constraints:pertype")
	for k,v in keyvals.items():
		#print(k,v)
		if k=='pertype':
			pertype=v.lower()#因为大小写区分，所以全部小写方便比较
		else:
			pass
	print('pertype=',pertype)
	
	constraintinfo['pertype'].append(pertype)
	return 1
	
#
#条目类型限制,将类型限制信息放入字典				
def mappernottype(keyvals,constraintinfo):
	
	print("constraints:pernottype")
	for k,v in keyvals.items():
		#print(k,v)
		if k=='pernottype':
			pernottype=v.lower()#因为大小写区分，所以全部小写方便比较
		else:
			pass
	print('pertype=',pertype)
	
	constraintinfo['pernottype'].append(pernottype)
	return 1
 
								
#
#条目类型转换				
def maptypesource(keyvals,bibentry,typesrcinfo):
	retrunval=1
	for k,v in keyvals.items():
		#print(k,v)
		if k=='typesource':
			typesource=v.lower()
		elif k=='typetarget':
			typetarget=v.lower()
		elif k=='final':
			retrunval=0
		else:
			pass
		
	typesrcinfo
	if typetarget:
		if bibentry['entrytype']==typesource:
			bibentry['entrytype']=typetarget
			typesrcinfo['typesource']=typesource
			return 1
		else:
			return retrunval #存在final时，且不匹配则终止map
	else:
		if bibentry['entrytype']==typesource:
			typesrcinfo['typesource']=typesource
		else:
			typesrcinfo['typesource']=None
		return retrunval
#
#
# 域信息设置
def mapfieldset(keyvals,bibentry,typesrcinfo,fieldsrcinfo,constraintinfo):
	overwrite=False
	append=False
	
	setcontinue=True
	print(setcontinue)
	if len(constraintinfo['pertype'])>0:
		if bibentry['entrytype'] not in constraintinfo['pertype']:#
			setcontinue=False
	if len(constraintinfo['pernottype'])>0:
		if bibentry['entrytype'] in constraintinfo['pernottype']:#
			setcontinue=False
	print(setcontinue)
	
	if setcontinue:
	
		for k,v in keyvals.items():
			#print(k,v)
			if k=='fieldset':
				fieldset=v.lower()
			elif k=='fieldvalue':
				fieldvalue=v
			elif k=='origfieldval':
				fieldvalue=fieldsrcinfo[fieldsrcinfo['fieldsource']]
				print(fieldvalue)
			elif k=='origentrytype':
				fieldvalue=typesrcinfo['typesource']
				print(fieldvalue)
			elif k=='origfield':
				fieldvalue=fieldsrcinfo['fieldsource']
				print(fieldvalue)
			elif k=='null':
				fieldvalue=None
				print(fieldvalue)
			elif k=='append':
				append=v
			elif k=='overwrite':
				overwrite=v
			else:
				pass
				
		
		print("fieldset=",fieldset)
		if overwrite:
			if append:
				oldvalue=bibentry[fieldset]
				newvalue=oldvalue+","+fieldvalue
				bibentry[fieldset]=newvalue
			else:
				bibentry[fieldset]=fieldvalue
		else:
			if fieldset in bibentry:
				pass
			else:
				bibentry[fieldset]=fieldvalue
		return 1
		
	else:
		return 1
	
#
#域名转换或判断域是否存在或match
def mapfieldsource(keyvals,bibentry,fieldsrcinfo,constraintinfo):
	mapfieldtype=0 #域名map的类型设置
	fieldmatch=''#匹配模式默认为空
	fieldmatchi=''#匹配模式默认为空
	
	
	setcontinue=True
	print(setcontinue)
	if len(constraintinfo['pertype'])>0:
		if bibentry['entrytype'] not in constraintinfo['pertype']:#
			setcontinue=False
	if len(constraintinfo['pernottype'])>0:
		if bibentry['entrytype'] in constraintinfo['pernottype']:#
			setcontinue=False
	print(setcontinue)
	
	
	overwrite=False
	for k,v in keyvals.items():
		#print(k,v)
		if k=='fieldsource':
			fieldsource=v.lower()
		elif k=='fieldtarget':
			fieldtarget=v.lower()
			mapfieldtype=1 #域map类型1，直接做域名转换
		elif k=='replace':
			fieldreplace=v
			mapfieldtype=2 #域map类型2，直接做域信息转换
		elif k=='final':
			fieldfinal=v #final要么选项不给出，要么选项给出为true
			if fieldfinal:#当为true时则做终止判断
				mapfieldtype=3 #域map类型3，做final判断可以终止map
		elif k=='overwrite':#
			overwrite=v
		elif k=='match':#不区分大小写的match
			fieldmatch=v
		elif k=='matchi':#区分大小写的match
			fieldmatchi=v
		elif k=='notmatch':#不区分大小写的notmatch，下面这两个选项的逻辑没有实现
			fieldnotmatch=v
		elif k=='notmatchi':#区分大小写的notmatch
			fieldnotmatch=v
		else:
			pass
	
	
	if setcontinue:

		#返回字典的第一项是fieldsource信息
		fieldsrcinfo['fieldsource']=fieldsource
		
		if mapfieldtype==0:#第0中情况即，不做信息转换，也不终止map，仅返回一些信息
		
			if fieldsource in bibentry:
				if fieldmatch:
					m = re.match(fieldmatch, bibentry[fieldsource])
					if m:
						fieldsrcinfo[fieldsource]=[bibentry[fieldsource],fieldmatch]
					else:
						fieldsrcinfo[fieldsource]=[None] #正则不匹配，则返回为None

				elif fieldmatchi:
					m = re.match(fieldmatchi, bibentry[fieldsource])
					if m:
						fieldsrcinfo[fieldsource]=[bibentry[fieldsource],fieldmatchi]
					else:
						fieldsrcinfo[fieldsource]=[None] #正则不匹配，则返回为None
					
				else:
					fieldsrcinfo[fieldsource]=bibentry[fieldsource]#将域的值记录下来，用于下一step
			
			else:
				fieldsrcinfo[fieldsource]=[None] #域不存在则返回为None
			return 1
			
		
		elif mapfieldtype==1:#第1中情况即，做域名转换
			print('fieldsource=',fieldsource,'fieldtarget=',fieldtarget)
			if fieldsource in bibentry:
				bibentry[fieldtarget]=bibentry[fieldsource]
				del bibentry[fieldsource]
				fieldsrcinfo[fieldsource]=bibentry[fieldtarget]
			else:
				fieldsrcinfo[fieldsource]=[None]
			return 1
		
		
		elif mapfieldtype==2:#域map类型2，直接做域信息转换，真正操作需要overwrite选项支持
			print('fieldsource=',fieldsource)
			print('fieldmatch=',fieldmatch)
			print('fieldreplace=',fieldreplace)
			if overwrite:
				if fieldsource in bibentry:
					if fieldmatch:
						#strafrpl=re.sub(r'(\d\d\d\d)\-(\d)\-(\d)',r'\1-0\2-0\3','2015-1-3')
						#strafrpl=re.sub(r'(\d\d\d\d)\-(\d)\-(\d)',r'\1-0\2-0\3',bibentry[fieldsource])
						strafrpl=re.sub(fieldmatch,fieldreplace,bibentry[fieldsource]) #执行替换
						print('strafterreplace=',strafrpl)
						bibentry[fieldsource]=strafrpl
					elif fieldmatchi:
						strafrpl=re.sub(fieldmatchi, fieldreplace,bibentry[fieldsource]) 
						bibentry[fieldsource]=strafrpl
					else:
						fieldsrcinfo[fieldsource]=[None]
				else:
					fieldsrcinfo[fieldsource]=[None]
			else:
				fieldsrcinfo[fieldsource]=[None]
			return 1

		
		elif mapfieldtype==3:#域map类型3，当没有匹配则终止map
			if fieldsource in bibentry:
				if fieldmatch:
					m = re.match(fieldmatch, bibentry[fieldsource])
					if m:
						fieldsrcinfo[fieldsource]=[bibentry[fieldsource],fieldmatch]
						return 1
					else:
						return 0

				elif fieldmatchi:
					if m:
						fieldsrcinfo[fieldsource]=[bibentry[fieldsource],fieldmatchi]
						return 1
					else:
						return 0
					
				else:
					fieldsrcinfo[fieldsource]=bibentry[fieldsource]#将域的值记录下来，用于下一step
					return 1
			
			else:
				return 0
	
	else:
		fieldsrcinfo[fieldsource]=[None]
		return 1
	
					
				

		
#运行脚本测试
if __name__=="__main__":
	
	#设置需要修改的bib文件
	#inputbibfile='example.bib'
	#inputbibfile='biblatex-map-test.bib'
	inputbibfile='eg-thesis.bib'
	
	#auxfile="opt-gbpub-true.aux"
	#set the aux file
	#this is not necessary
	auxfile=''
	#auxfile="opt-gbpub-true.aux"
	
	readfilecontents(inputbibfile)
	
	#printfilecontents()

	bibentryparsing()
	
	#printbibentries()
	
	execsourcemap()
	
	#printbibentries()
	
	writefilenewbib(inputbibfile)
	
	#print(bibentries[0])

	#print(formatbibentry(bibentries[0]))
	
	formatallbibliography()
	printbibliography()
		