vim嵌套的一行循环中断命令



我想为文件中的特定行多次附加一个字符,这样所有行都会有x个字符

假设我希望20到80之间的所有行都有相同数量的字符(50(,并在末尾附加相同的字符:

for y in range(20, 80) | if strlen(getline(y)) !=50 | for i in range(50-strlen(getline(y))) | execute y .. 's/$/./' | endfor | endif | endfor

退货CCD_ 2和CCD_ 3

如果我把它和一条特定的线路一起使用,效果很好if strlen(getline(N)) !=50 | for i in range(50-strlen(getline(N))) | execute N .. 's/$/./' | endfor | endif

例如:

输入:

abcdef
defghijklm
foo

输出:

abcdef**********
defghijklm******
foo*************

这些错误来自哪里?

  • E727: Start past end

    此错误是由range(50-strlen(getline(y)))中的公式50-strlen(getline(y))引起的,当第y行的字符数超过50时,该公式会返回:help range()不喜欢的负数。

  • E1098: String, List or Blob required

    此错误是上一个错误的结果:range(50-strlen(getline(y)))不返回任何可以循环的内容,因此:for无法工作。

这些错误可能可以通过向您的";一个衬垫";但这似乎不是一个好主意,哪怕只是因为你的命令已经太复杂了。

使用一个简单得多的可以更可靠地实现所需的结果:

:20,80s/$/=repeat('*',50-strlen(getline('.')))
  • 它是一个具有范围、模式和:help sub-replace-special表达式的快速:help :substitute
  • 20,80是我们的范围,请参阅:help :range
  • $是我们的零宽度图案,即线条的末端
  • 非常强大的=<expr>允许我们使用<expr>返回的字符串作为替换
  • CCD_ 20将给定字符串重复给定次数
  • E727:Start past end1是我们的字符串
  • 重复次数是用你自己的公式计算出来的。当该行长于50时,重复次数为负,这意味着没有重复,因此没有*被附加到该行

之前:

a short line
some filler text foo
a line with 59 characters dgsfdsjgdfsjdshdlsjdfshjdsfdlhsjd
what

之后:

a short line**************************************
some filler text foo******************************
a line with 59 characters dgsfdsjgdfsjdshdlsjdfshjdsfdlhsjd
what**********************************************

使用GNU sed。先附加16颗星,然后只保留前16个字符。

sed -E 's/$/****************/; s/(.{16}).*/1/' file

输出:

abcdef**********defghijklm******foo*************

只需使用awk,它是为以下作业创建的:

$ cat file
line 1
line 2
line 3
abcdef
defghijklm
foo
line 7
line 8

$ awk '
BEGIN { wid=50; pad=sprintf("%*s",wid,""); gsub(/ /,"*",pad) }
4<=NR && NR<=6 { $0=substr($0 pad,1,wid) }
1' file
line 1
line 2
line 3
abcdef********************************************
defghijklm****************************************
foo***********************************************
line 7
line 8

更改宽度(50以上(和开始/结束行号(4和6以上(以适应。