Posso unir linhas com uma vírgula (ou outro caractere)?


19

Eu sei que posso unir linhas no Vim com Jdiversas variantes ( gJ, etc.); Jirá "Remover o recuo e inserir até dois espaços" .

Mas existe também uma maneira direta de inserir outro caractere em vez dos dois espaços? Por exemplo uma vírgula ( ,) ou vírgula e espaço ( ,)?

Dado:

8
9
10
32

Eu gostaria de terminar com:

8, 9, 10, 32

ou:

8,9,10,32

Você também pode gostar de github.com/sk1418/Join (não testado).
VanLaser

Respostas:


5

Eu escrevi um plugin Join, pode fazer o que você quiser e muito mais.

Exceto por todos os recursos fornecidos pelo comando build-in: join, o Join pode:

  • Unir linhas ao separador (string)
  • Unir linhas com ou sem aparar os espaços em branco iniciais / finais
  • Associar linhas com contagem negativa (associação reversa)
  • Unir linhas ao contrário
  • Unir linhas e manter linhas unidas (sem remover linhas unidas)
  • Unir linhas com qualquer combinação das opções acima

mais detalhes e capturas de tela:

https://github.com/sk1418/Join


23

Uma maneira simples é a seguinte: basta selecionar suas linhas (exceto a última) - ou use %- e execute:

:'<,'>s/\n/,/

ou

:'<,'>s/\n/, /

(onde, é claro, a '<,'>peça já foi inserida depois :pelo Vim, para segmentar a seleção)


(2) Atualização:

Com base no exposto acima (e no comentário de Sato Katsura ), aqui está uma possível implementação de "junção interativa", com contagem e suporte repetido opcional:

" ================ 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>

E um mapeamento real:

"================= vimrc ================================================
nmap J <Plug>(interactiveJoin)
xmap J <Plug>(interactiveJoin)
nmap gJ <Plug>(interactiveGJoin)
xmap gJ <Plug>(interactiveGJoin)

É como (*) J, mas interativo - ele solicitará a sequência separadora. A sequência padrão é um espaço - portanto, por exemplo, para unir linhas sem separador, pressione Backspacequando solicitado, para remover o caractere de espaço padrão e Enterpara aceitar o (agora) separador vazio. Contagem, por exemplo 3J, também funciona. Se o tpope/vim-repeatplug-in estiver instalado, repita com '.' também funcionará, reutilizando o último separador e (se não for alterado - por exemplo 10.) a última contagem ou intervalo de linhas visuais.


(*) Porém, não é exatamente assim J: embora remova o recuo, ele não procurará .!?(no final da frase) inserir 2 espaços em vez de um ou inserir um espaço apenas se estiver ausente (é difícil fazer algo como isso, já que a cadeia separadora pode ser qualquer coisa agora). Também removerá espaços à direita (faz mais sentido).

Eu acho que essa pode ser uma boa maneira de sobrecarregar o espaço limitado de letras dos operadores :)

Bem, tecnicamente Jnão é um operador, mas um operador - por exemplo, você não pode fazer isso Jawpara juntar "uma palavra".

(sugestões são bem-vindas)

insira a descrição da imagem aqui


2
Melhor ainda: :'<,'>-1s/\n/, /para linhas marcadas ou :1,$-1s/\n/, /para o arquivo inteiro.
Sato Katsura

Na verdade, isso é ainda melhor :)
VanLaser

@SatoKatsura você pode explicar o -1?
Alxndr

1
@alxndr - é usado para pular a última linha no intervalo / arquivo: por exemplo, no exemplo do OP, você não quer uma vírgula após 32 e também não deseja associá-la à próxima linha, se existir. . Você pode até usar '<,'>-s/\n/, /ou 1,$-s/\n/, /como -é o mesmo que -1.
VanLaser

1
Se l:sepfor um &, sua substituição funcionará incorretamente, pois &é mágica na substituição. Pode ser melhor usar o \=para usar uma string literal - let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"- em vez de tentar lidar com a fuga.
jamessan

3

Aqui está um exemplo usando o comando externo:

:%!paste -sd,

onde %!substitui o buffer atual (conteúdo do arquivo) pelo comando: paste -sd,(parameters -sé usado para unir várias linhas e -ddefine o caractere delimitador como ,).


3

Caso alguém não goste de digitar Regex e memorizar mais comandos Plugin Ex:

Anexar bloco visual

Visual-block Append está disponível no modo Visual Block ( <C-v>) e pode fazer um bloco A ppend (e bloquear I NSERT para preceder). (ref: :help v_b_A, :help v_b_I)

E se o último movimento no Modo Visual de Bloco for $, o acréscimo será feito no final de todas as seleções; ou então espaços serão inseridos antes do texto que você anexou (imagine alinhar o fechamento )no final de várias chamadas de método no código).

Com texto de exemplo abaixo e cursor ligado 8:

8
9
10
12

<C-v>}$A,<C-c>. Depois de voltar ao modo normal, podemos ver que ,é anexado a todas as linhas selecionadas. (Tente sem $)

Em seguida, faça gvpara selecionar novamente a área e Jou gJ. Temos um rastro ,: 8,9,10,12,e $xterminamos.

Usar inserção para não arrastar ,

Vamos desfazer o nosso texto (seja ele uu..usofisticado :ea 1d<cr>:lat 1) e tentar o Visual Insert:

j<C-v>}I, <C-c>e então podemos juntar as linhas gJsem espaços.

Espere, espere, algo está faltando. Como selecionar novamente toda a "matriz"? Desta vez, não selecionamos a primeira linha ... então gvnão ajuda.

- Ou pode ajudar, gvoké re-selecionar ( gv), ocanto oposto e para kcima.

PS meu mindinho não é rápida e precisa o suficiente para escrever /\para /\n, então eu como a combinação de Vim built-in operações e movimentos para evitar o uso de Regex. No entanto, se eu fizer isso com bastante frequência, usando um mapeamento - talvez aqueles que mapeiem para plugins devam ser melhores.


1

Uma maneira muito mais simples, sem plugins ou comandos externos, de remapear join ( J) de um espaço para o caractere que você gosta. Por exemplo, para se juntar a uma vírgula e um espaço:

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

Para a nova linha de caractere especial no final ( ^M), pressione Ctrl-Ve, em seguida, Return / Enter. O mesmo vale se você deseja substituir por uma guia ( ^I), digite Ctrl-Ientão Tab.

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

O que isto está fazendo é substituir uma nova linha por uma guia na linha atual e remapear esse comportamento para o caractere J.

Isso também funciona com combinações, como em 4Jjuntar-se aos próximos 4 linhas.


0

Você pode gravar uma macro para unir linhas com uma vírgula. Isso é útil se for uma tarefa rara ou pontual e você não consegue se lembrar de como escrever um comando substituto e uma expressão regular para executar a tarefa, mas lembra-se de como gravar e executar uma macro.

Para unir linhas com uma vírgula, digite qjgJi,Escqpara registrar a macro no registro j. Então você pode executar a macro com @j. Você pode executar novamente a macro com @@, o que economiza na digitação ao executá-la várias vezes seguidas - você pode até manter pressionado @até chegar perto do final das linhas nas quais deseja ingressar. Você também pode usar um prefixo numérico @jou @@repeti-lo um número definido de vezes. Isso deixa o espaço inicial e final intacto, para que haja espaços antes ou depois da vírgula, se o texto original tiver espaços lá.

Para juntar uma vírgula e um espaço, insira Spaceentre ,e Escao gravar a macro.

Você também pode usar em Jvez de gJgravar a macro, que geralmente une linhas com vírgula e espaço. No entanto, se a linha atual tiver espaços em branco à direita, a vírgula aparecerá após o espaço em branco sem um espaço a seguir. Além disso, ele não inclui o espaço se a próxima linha começa com ), e ele coloca dois espaços após a vírgula, se joinspacesestiver definido e as extremidades de linha atuais com ., !ou ?. Essas advertências são descritas abaixo :help J.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.