基于字典的搜索和替换

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)

你可以……

  1. 在映射文件中打开这些行(/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
    ...
    
  2. 写入文件:

    :w 
    
  3. 并从您的 JSON 文件中获取:

    :source /tmp/mappings
    

参见 :help :g:help :s:help :normal:help :range:help :source:help pattern-delimiter