前言
因为工作的需求经常需要把一些文本模式的字符串转为指定的格式,如:
json格式化
时间戳转时间
时间转时间戳
生成时间字符串
每次都需要连网使用一些在线小工作,但是好多时间又需要断开Internat只连内网,
经常用Vim,Vim如此强大能不能直接在Vim里实现呢?
环境:
操作系统:Windows10
Python:3.6.8
Vim:8.1
第一步:需求
- 可以把unicode编码的json文本转为标准json
- 可以把utf-8未解码的json转为标准json
- 把时间转为时间戳
- 把时间戳转是标准时间,例:2019-12-31 12:00:00
第二步:python实现
fs.py代码:
# -*- coding: utf-8 -*-
import argparse
import collections
import datetime
import json
import sys
import time
def parse_datetime(str_time=None, fmt='%Y-%m-%d %H:%M:%S'):
"""
将时间字符串解析为时间
:param str_time:
:param fmt:
:return:
"""
t = datetime.datetime.now()
if str_time:
try:
t = datetime.datetime.strptime(str_time, fmt)
except:
try:
t = datetime.datetime.strptime(str_time, '%Y/%m/%d %H:%M:%S')
except:
try:
# UTC时间转为北京时间需要加上8小时时差
t = datetime.datetime.strptime(str_time, '%Y-%m-%dT%H:%M:%SZ')
t += datetime.timedelta(hours=8)
except:
try:
# UTC时间转为北京时间需要加上8小时时差
t = datetime.datetime.strptime(str_time, '%Y-%m-%dT%H:%M:%S.%fZ')
t += datetime.timedelta(hours=8)
except Exception as e:
t = t
return t
def str_to_timestamp(str_time=None, fmt='%Y-%m-%d %H:%M:%S'):
"""时间转时间戳"""
str_time = str(str_time)
convert_timestamp = str_time
if str_time:
if str_time.isdigit():
if len(str_time) == 10:
convert_timestamp = int(str_time)
else:
convert_timestamp = int(str_time) / 1000
else:
d = parse_datetime(str_time, fmt)
convert_timestamp = int(time.mktime(d.timetuple()))
return convert_timestamp
def timestamp2str(ts, fmt='%Y-%m-%d %H:%M:%S'):
ts = str(ts)
convert_str = ts
if ts.isdigit():
ts = int(ts[0:11])
convert_str = time.strftime(fmt, time.localtime(ts))
return convert_str
def main():
parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType())
parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'))
options = parser.parse_args()
infile = options.infile or sys.stdin
outfile = options.outfile or sys.stdout
with infile:
try:
content = infile.read()
# 转义未解码的utf-8
if "\\x" in content:
content = content.replace("'", "\"")\
.replace("\r\n","")\
.replace("\n","")\
.replace("\r","")
content = eval("b'" + content + "'").decode('utf8')
obj = json.loads(content, object_pairs_hook=collections.OrderedDict)
except Exception as e:
raise SystemExit(e)
try:
# unicode
if "\\u" in content:
obj = json.loads("u'" + content.strip() + "'")
else:
# 时间
obj = str(str_to_timestamp(content))
except:
obj = content
# 时间戳转时间
if isinstance(obj, int):
obj = timestamp2str(int(content))
# raise SystemExit(e)
with outfile:
if isinstance(obj, dict) or isinstance(obj, list):
json.dump(
obj,
outfile,
indent=4,
ensure_ascii=False
)
outfile.write('\n')
elif isinstance(obj, str) or isinstance(obj, int):
outfile.write(str(obj))
outfile.write('\n')
if __name__ == '__main__':
main()
测试数据:
数据1:
{"shanghai": "\u4e0a\u6d77", "zhengzhou": "\u90d1\u5dde"}
数据2:
{'shanghai': '\xe4\xb8\x8a\xe6\xb5\xb7', 'zhengzhou': '\xe9\x83\x91\xe5\xb7\x9e'}
数据3:
1577793600
数据4:
2019-12-31 18:13:39
将该数据放在一个文本中然后以该文本文件的名称如(test)作为参数
第三步:将该Python脚本加入到sys根目录下
wedo.pth内容:
D:\Workspace\Github\myconf\vim\cmd\python
上面的路径是fs.py路径所在位置
然后把该文件放在site-packages目录下,甚至具体哪个目录不同的环境目录也不同,自己找吧
如还是不知道,可以用如下脚本打印一下:
import site;
print(site.getsitepackages())
执行命令如下:
python -m fs test
第四步:在vim配置文件中添加相关配置
command! FS :execute ‘%!python -m fs’
它的意思是在vim的ex模式下输入FS会调用我们的Python脚本
第五步:使用
OK这个时候就可以把打开Vim把需要的文本格式化为任意想要的格式了,命令如下:
:FS
总结
虽然这样可以目标实现了,但是目前为止还是有缺陷的:
文本文件中全部的内容必须是要格式化的文本,否则的话会报错
一个不那么友好的解决方式是先选中指定的文本,然后直接调用python而不是指定的命令:
:!python -m fs
中间的’<,’>这个不用管,它代表上面你选中的内容,当你选中之后按冒号(:)会自动出现的
有更好的实现方式欢迎指正哈