基于字典的搜索和替换
Search and replace based on a dictionary
我有一个 json 文件,其中包含一个数据列表,其中每个元素都有一个名为 url 的字段。
[
{ ...,
...,
"url": "us.test.com"
},
...
]
在另一个文件中,我有一个映射列表,我需要将受影响的 url 字段替换为,格式如下:
us.test.com test.com
hello.com/se hello.com
...
所以最终结果应该是:
[
{ ...,
...,
"url": "test.com"
},
...
]
有没有办法在 Vim 中执行此操作,还是我需要以编程方式执行此操作?
好吧,我会在 Vim 中以编程方式执行此操作;-) 如您所见,它与 Python 和许多其他脚本语言非常相似。
假设我们打开了 json 个文件。那么
:let foo = json_decode(join(getline(1, '$')))
会将 json 加载到 Vim 脚本变量中。所以 :echo foo
将显示 [{'url': 'us.test.com'}, {'url': 'hello.com/se'}]
.
现在让我们切换到“映射”文件。我们将拆分所有行并制作一个这样的字典:
:let bar = {}
:for line in getline(1, '$') | let field = split(line) | let bar[field[0]] = field[1] | endfor
现在 :echo bar
按预期显示 {'hello.com/se': 'hello.com', 'us.test.com': 'test.com'}
。
要执行替换,我们只需执行以下操作:
:for field in foo | let field.url = bar->get(field.url, field.url) | endfor
现在 foo
包含 [{'url': 'test.com'}, {'url': 'hello.com'}]
,这就是我们想要的。剩下的步骤是用
将新值写入缓冲区
:put =json_encode(foo)
你可以……
在映射文件中打开这些行(/tmp/mappings
用于说明目的):
us.test.com test.com
hello.com/se hello.com
...
进入:
g/"url"/s@us.test.com@test.com@g
g/"url"/s@hello.com/se@hello.com@g
...
与:
:%normal Ig/"url"/s@
:%s/ /@
我们的想法是将文件变成一个脚本,该脚本将在匹配 "url"
.
的所有行上执行所有这些替换
如果您确信这些字符串仅在 "url"
行中,您可以这样做:
:%normal I%s@
:%s/ /@
获得:
%s@us.test.com@test.com@g
%s@hello.com/se@hello.com@g
...
写入文件:
:w
并从您的 JSON 文件中获取:
:source /tmp/mappings
参见 :help :g
、:help :s
、:help :normal
、:help :range
、:help :source
和 :help pattern-delimiter
。
我有一个 json 文件,其中包含一个数据列表,其中每个元素都有一个名为 url 的字段。
[
{ ...,
...,
"url": "us.test.com"
},
...
]
在另一个文件中,我有一个映射列表,我需要将受影响的 url 字段替换为,格式如下:
us.test.com test.com
hello.com/se hello.com
...
所以最终结果应该是:
[
{ ...,
...,
"url": "test.com"
},
...
]
有没有办法在 Vim 中执行此操作,还是我需要以编程方式执行此操作?
好吧,我会在 Vim 中以编程方式执行此操作;-) 如您所见,它与 Python 和许多其他脚本语言非常相似。
假设我们打开了 json 个文件。那么
:let foo = json_decode(join(getline(1, '$')))
会将 json 加载到 Vim 脚本变量中。所以 :echo foo
将显示 [{'url': 'us.test.com'}, {'url': 'hello.com/se'}]
.
现在让我们切换到“映射”文件。我们将拆分所有行并制作一个这样的字典:
:let bar = {}
:for line in getline(1, '$') | let field = split(line) | let bar[field[0]] = field[1] | endfor
现在 :echo bar
按预期显示 {'hello.com/se': 'hello.com', 'us.test.com': 'test.com'}
。
要执行替换,我们只需执行以下操作:
:for field in foo | let field.url = bar->get(field.url, field.url) | endfor
现在 foo
包含 [{'url': 'test.com'}, {'url': 'hello.com'}]
,这就是我们想要的。剩下的步骤是用
:put =json_encode(foo)
你可以……
在映射文件中打开这些行(
/tmp/mappings
用于说明目的):us.test.com test.com hello.com/se hello.com ...
进入:
g/"url"/s@us.test.com@test.com@g g/"url"/s@hello.com/se@hello.com@g ...
与:
:%normal Ig/"url"/s@ :%s/ /@
我们的想法是将文件变成一个脚本,该脚本将在匹配
的所有行上执行所有这些替换"url"
.如果您确信这些字符串仅在
"url"
行中,您可以这样做::%normal I%s@ :%s/ /@
获得:
%s@us.test.com@test.com@g %s@hello.com/se@hello.com@g ...
写入文件:
:w
并从您的 JSON 文件中获取:
:source /tmp/mappings
参见 :help :g
、:help :s
、:help :normal
、:help :range
、:help :source
和 :help pattern-delimiter
。