vim 如何复制一个关键字:值下面的一个块,并重复这一点,为每个后续块?

5lhxktic  于 2022-11-11  发布在  其他
关注(0)|答案(6)|浏览(185)

我有一个yaml文件,我需要在其中复制一个key:value(当:var)添加到下面的任务中,并且需要对每个块重复该操作。
现在的样子:

- set_fact: something
- set_fact: var_a
- task: do the foo
  when: var_a
- task: do the goo

- set_fact: something
- set_fact: var_b
- task: do the fofo
  when: var_b
- task: do the gogp

- set_fact: something
- set_fact: var_c
- task: do the fooolo
  when: var_c
- task: do the gooolo

我需要它看起来像:

- set_fact: something
- set_fact: var_a
- task: do the foo
  when: var_a
- task: do the goo
  when: var_a

- set_fact: something
- set_fact: var_b
- task: do the fofo
  when: var_b
- task: do the gogp
  when: var_b

- set_fact: something
- set_fact: var_c
- task: do the fooolo
  when: var_c
- task: do the gooolo
  when: var_c

从研究如何做到这一点,我认为一个vim循环可以做到这一点,但我不知道如何做到这一点。如果有人有任何提示,我会非常感激。
编辑:我所尝试的。用这个我捕获了我需要的值。(var_ values)

grep -e set_fact -B1 filterlist_playbook.yml|grep -e "^.*\:"|grep -v "set\_fact\:"|awk -F":" '{print $1}'

我用两种不同的方法尝试过。
1首先添加“when:“字段,然后复制/粘贴var_ value添加when:字段与sed是可以的。按顺序粘贴正确的值...我没有找到如何做到这一点的信息,我的同事也不知道。
2复制/粘贴“当:同样,用sed捕捉正确的值是可以的,顺序粘贴它会让我挠头,谷歌搜索就会被遗忘。
注:我一定会选择一个工作答案,但它需要我的时间来尝试每一个。

bjp0bcyl

bjp0bcyl1#

下面是我在Vim中的做法:

:g/when/normal mzvip^[:'zt'>^M

其中^[是用<C-v><Esc>获得的,^M是用<C-v><CR>获得的。
明细:

  • :g/<pattern>/<command>在与<pattern>匹配的每一行上执行<command>
  • :normal xxx从命令行模式执行常规命令。
  • mz将标记'z放置在匹配行上。
  • vip可视地选择当前段落,并在其最后一行放置标记'>
  • <Esc>退出可视模式。
  • :'zt'>将带有标记'z行复制到带有标记'>行下面
  • <CR>执行最后一个命令。

请参阅:help :global:help :normal:help mark-motions:h :t:h :range
请注意,直观地使用标记'},如下所示:

:g/when/t'}

看起来它可以很好地解决这个问题,但是Vim在实际段落后的第一个空行上做了标记'},这对我们没有帮助,因为我们的锚是实际段落的最后一行。
这就是为什么vip舞蹈是必要的原因之一:我们需要在段落的最后一行上,而不是在之后添加一个标记,并且可视地选择“内部段落”就可以使用标记'>来实现这一点。

rnmwe5a2

rnmwe5a22#

使用awk可以执行以下操作:

awk -F ': ' '
$1 ~ / when$/ {var = $0}
NR > 1 {print prev}
!NF && prev ~ /^- task/ {print var}
{prev = $0}
END {
   print prev
   if (prev ~ /^- task/)
      print var
}' file

输出:

- set_fact: something
- set_fact: somethingelse
- task: do the foo
  when: var_a
- task: do the goo
  when: var_a

- set_fact: something
- set_fact: somethingelse
- task: do the fofo
  when: var_b
- task: do the gogp
  when: var_b

- set_fact: something
- set_fact: somethingelse
- task: do the fooolo
  when: var_c
- task: do the gooolo
  when: var_c
2izufjch

2izufjch3#

在vim中,你可以这样做:

  • qq开始录制名为q的宏
  • /when: Enter查找下一个出现的when:
  • yy猛拉当前行
  • j向下移动光标
  • p在下面粘贴线条
  • q终止宏录制

此时,您可以根据需要键入@q来多次调用宏。
你也可以提前知道你需要执行多少次这样的操作,用:%s/when://ng来查找when:的出现次数,这将打印出类似3 matches on 3 lines的内容。然后你可以只键入例如3@q来调用宏3次。

1bqhqjot

1bqhqjot4#

If ed is available/acceptable.

printf '%s\n' 'g/^[[:space:]]\{1,\}when: var_.*/t.1' ,p Q | ed -s file.yaml

If the output is correct, and in-place editing is needed, change

,p Q

to

w q

I only have GNU ed at hand.

  • g

Globally substitute for all non-overlapping instances of the RE rather than just the first one. If both g and count are specified, the results are unspecified.

  • (1,$) g /RE/command list
  • (.,.) t address

The t command shall be equivalent to the m command, except that a copy of the addressed lines shall be placed after address address (which can be 0); the current line number shall be set to the address of the last line added.

  • .

The period character ( . ) shall address the current line.

  • The positive decimal number n shall address the nth line of the edit buffer.
  • , or %

Depending on the variant shall address the whole buffer. ,p or %p

  • (.,.) p

The p command shall write to standard output the addressed lines; the current line number shall be set to the address of the last line written. The p command can be appended to any command other than e, E, f, q, Q, r, w, or !.

  • w The w command shall write the addressed lines into the file named by the pathname file.
  • q

The q command shall cause ed to exit. If the buffer has changed since the last time the entire buffer was written, the user shall be warned, as described previously.

  • Q

The Q command shall cause ed to exit without checking whether changes have been made in the buffer since the last w command.

  • -s Suppress the writing of byte counts by e, E, r, and w commands and of the '!' prompt after a !command.

See

In vim something like.

:g/^[[:space:]]*when: var_.*/t.1
rks48beu

rks48beu5#

要从输入中得到输出,您需要使用任何awk:

$ awk -v RS= -F'\n' '{print $0 ORS $(NF-1) ORS}' file
- set_fact: something
- set_fact: var_a
- task: do the foo
  when: var_a
- task: do the goo
  when: var_a

- set_fact: something
- set_fact: var_b
- task: do the fofo
  when: var_b
- task: do the gogp
  when: var_b

- set_fact: something
- set_fact: var_c
- task: do the fooolo
  when: var_c
- task: do the gooolo
  when: var_c

或者如果实际输入比前面显示的更复杂,也可以使用任何awk:

$ awk '/when:/{w=$0} {print} /task:/ && w{print w; w=""}' file
- set_fact: something
- set_fact: var_a
- task: do the foo
  when: var_a
- task: do the goo
  when: var_a

- set_fact: something
- set_fact: var_b
- task: do the fofo
  when: var_b
- task: do the gogp
  when: var_b

- set_fact: something
- set_fact: var_c
- task: do the fooolo
  when: var_c
- task: do the gooolo
  when: var_c

相关问题