我知道我可以使用J及其几个变体(gJ等)在Vim中加入行; J将“删除缩进并最多插入两个空格”。

但是还有直接插入另一个字符而不是两个空格的简单方法吗?例如逗号(,)或逗号和空格(,)吗?

给出:

8
9
10
32


我想结束:

8, 9, 10, 32


或:

8,9,10,32


评论

您还可能喜欢github.com/sk1418/Join(未经测试)。

所有这些答案都是无用的。请立即访问unix.stackexchange.com/a/338124/107860,以获得即时答案。

@lobi不是Vim吗?此外,sed与:%s /../../?
大致相同

#1 楼

我写了一个Join插件,可以做您想做的事情,还有很多事情。


带分隔符的连接线(字符串)
有或没有修剪前/后空格的连接线
负数连接线(向后连接)
>反向连接线
连接线并保持连接线(不删除连接线)
使用以上选项的任意组合连接线




更多详细信息和屏幕截图:

https://github.com/sk1418/Join

#2 楼

一种简单的方法是:只需选择您的行(除最后一行以外的所有行)-或使用%-并运行: >
:'<,'>s/\n/,/


(当然,其中Vim在'<,'>之后已经插入了:部分,以定位选择) br />
在上面的内容(以及Sato Katsura的评论)的基础上,这是一个可能的“交互式联接”实现,具有计数和可选的重复支持:

:'<,'>s/\n/, /
>和实际的映射:

" ================ script ===============================================
" interactive 'J', 'gJ' replacement with optional 'vim-repeat' support
" The last used separator is automatically reused as:
" a. default choice
" b. when repeating (=> non-interactive repeats: same range, same separator)
let g:last_join_separator = " "
function! s:interactiveJoin(use_last_sep,...) range
    if (a:use_last_sep == 0) "interactive, ask for separator to use
        call inputsave()
        echohl Question
        let l:sep = input("Separator:", g:last_join_separator)
        echohl None
        call inputrestore()
        redraw!
        let g:last_join_separator = l:sep "update last separator value
    else "non-interactive (when repeating with '.')
        let l:sep = g:last_join_separator
    endif
    if (a:0 == 0) "with no argument, remove indentation *and trailing spaces*
        let l:subst = 's/\s*\n\+\s*/\=' . "'" . l:sep . "'/"
    else " don't remove indentation or trailing spaces (act like 'gJ')
        let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"
    endif
    if a:firstline < a:lastline "join given range
        execute a:firstline . ',' . (a:lastline - 1) . l:subst
        let l:count = a:lastline - a:firstline + 1 "default count for repeat
    else "or join only with next line
        execute l:subst
        let l:count = 1 "default count for repeat
    endif
    "make command repeatable
    "(with the tpope/vim-repeat plugin: optional, recommended)
    if (a:0 == 0)
        silent! call repeat#set("\<Plug>(repeatJoin)", l:count)
    else
        silent! call repeat#set("\<Plug>(repeatGJoin)", l:count)
    endif
endfunction

noremap <silent> <Plug>(interactiveJoin)  :call <SID>interactiveJoin(0)<CR>
noremap <silent> <Plug>(interactiveGJoin) :call <SID>interactiveJoin(0,'g')<CR>
noremap <silent> <Plug>(repeatJoin)       :call <SID>interactiveJoin(1)<CR>
noremap <silent> <Plug>(repeatGJoin)      :call <SID>interactiveJoin(1,'g')<CR>


这有点像J,但是是交互式的-它会提示输入分隔符字符串。默认字符串是空格-例如,要连接不带分隔符的行,请在提示时按Backspace,删除默认的空格字符,然后按Enter接受(现在)空分隔符。计数,例如3J,也可以。如果安装了tpope/vim-repeat插件,则以“。”重复。也可以使用,重新使用最后一个分隔符和(如果未更改,例如10.)最后一个计数或可视行范围。


(*)它与J并不完全相同,尽管:虽然会删除缩进,它不会检查.!?(词尾)是插入2个空格而不是一个空格,或者仅在缺少空格时才插入空格(很难做这样的事情,因为分隔符字符串现在可以是任何东西) 。它还会删除尾随空格(更有意义)。不是一个运算符,但是接近一个运算符-例如,您不能执行J来加入“一个单词”。

(欢迎提出建议)



评论


更好的是::'<,'>-1s / \ n /,/用于标记行,或:1,$-1s / \ n /,/对于整个文件。

–佐藤桂
2015年8月3日在8:33



确实,这甚至更好:)

– VanLaser
15年8月3日在8:35

@SatoKatsura你能解释-1吗?

– alxndr
15年8月3日在18:12

@alxndr-用于跳过范围/文件中的最后一行:例如在OP示例中,您不希望逗号在32之后,并且也不想将其与下一行连接(如果存在)。您甚至可以使用'<,'>-s / \ n /,/或1,$-s / \ n /,/--与-1相同。

– VanLaser
15年8月3日在20:41

如果l:sep是&,则替换将无法正常工作,因为&是替换中的魔术。最好使用\ =来使用文字字符串-让l:subst ='s / \ n \ + / \ ='。 “”。 l:sep “'/”-而不是尝试转义。

–詹姆斯
2015年8月5日在20:29



#3 楼

这是使用外部命令的示例:

:%!paste -sd,


其中%!用以下命令替换当前缓冲区(文件的内容):paste -sd,(参数-s用于连接多行和-d将分隔符设置为,)。

#4 楼

以防万一有人不喜欢输入正则表达式并记住更多的Plugin Ex命令:

Visual-block Append

Visual-block Append在Visual Block模式下可用(<C-v> ),并可以执行一个块追加(和块插入作为前置)。 (ref::help v_b_A:help v_b_I

如果“块可视模式”中的最后一个动作是$,则追加将在所有选择的结尾处完成;否则将在您添加的文本之前插入空格(可以想象在代码中几个方法调用的末尾对齐闭包))。

下面带有示例文本,并将光标放在8上: />
8
9
10
12


<C-v>}$A,<C-c>。回到正常模式后,我们可以看到,被附加到所有选定的行。 (尝试不使用$

然后执行gv重新选择区域和JgJ。我们已经完成了结尾,8,9,10,12,$x的操作已经完成。花哨的,),然后尝试使用Visual Insert:

uu..u,然后我们可以使用:ea 1d<cr>:lat 1将行加入空格。

等待,等待,缺少某些内容。如何重新选择整个“数组”?这次我们没有选择第一行...所以j<C-v>}I, <C-c>无济于事。 。

PS我的小指不够快速且不够准确,无法为gJ输入gv,因此我喜欢结合使用Vim内置的操作和动作来避免使用正则表达式。但是,如果我经常这样做,请使用映射-也许映射到插件的映射应该更好。

#5 楼

您可以记录宏以逗号分隔行。如果这是一项罕见的任务或一次性任务,这很有用,并且您不记得如何编写替代命令和正则表达式来执行任务,但是您确实记得如何记录和运行宏。 br />要用逗号连接行,请键入qjgJi,Escq将宏记录在寄存器j中。然后,您可以使用@j运行宏。您可以使用@@重新运行该宏,这样可以节省连续运行多次时的键入次数,甚至可以按住@直到到达要加入的行的末尾。您还可以在@j或@@上使用数字前缀将其重复设定的次数。这将保留前导和尾随空格,因此,如果您的原始文本中有空格,则在逗号之前或之后会有空格。

要加入逗号和空格,请在,和Esc之间插入空格录制宏时。

录制宏时,也可以使用J而不是gJ,通常会用逗号和空格连接行。但是,如果当前行具有尾随空格,则逗号将出现在空格之后,后面没有空格。另外,如果下一行以)开头,则不包含空格;如果设置了joinspaces且当前行以.!?结尾,则它在逗号后放置两个空格。这些警告在:help J下进行了描述。

#6 楼

一种无需插件或外部命令即可将空格(J)从空间重新映射到所需字符的简单得多的方法。例如,要用逗号和空格连接:

:nmap J :s/\n/, /^M


对于末尾的特殊字符换行符(^M),请按Ctrl-V,然后按Return / Enter。如果要替换为制表符(^I),请键入Ctrl-I,然后键入Tab,同样如此。行并将该行为重新映射到J字符。

这也可以与组合一起使用,如4J中所示,以连接下4行。

#7 楼

为了解决此限制,我们可以通过将其拆分为两个单独的简单问题来解决此问题: />
:%s/$/,/-:%s搜索整个文件,并用逗号($)替换每行(,

:%norm A,-对于文件中的每一行,请执行以下命令A,(附加,) br />在行尾添加子字符串的更多方法




%join连接行


此解决方案是比%s/\n/,/更容易提出。

评论


欢迎来到Vi和Vim!我喜欢您使用惯用语;这是一种快速而灵活的方法。我也喜欢$而不是\ n-并非所有文件都将\ n用作eol,因此实际上比:%substitute / \ n /,好!

– D. Ben Knoble♦
20-11-30在17:02