Como copiar os quatro primeiros caracteres de cada linha até o final da mesma linha?


10

Dada uma série de linhas parecidas com esta:

2001 "Some Kind of Title," Author's Name, Publication Name, 1 Mar.
2002 "Some Kind of Title," Author's Name, Publication Name, 12 Oct.
2003 "Some Kind of Title," Author's Name, Publication Name, 8 Apr.
2004 "Some Kind of Title," Author's Name, Publication Name, 3 Jun.

Existe uma maneira de eu pegar esses quatro primeiros caracteres (o ano) e copiá-los para o final da linha, para que fique assim:

2001 "Some Kind of Title," Author's Name, Publication Name, 1 Mar. 2001
2002 "Some Kind of Title," Author's Name, Publication Name, 12 Oct. 2002
2003 "Some Kind of Title," Author's Name, Publication Name, 8 Apr. 2003
2004 "Some Kind of Title," Author's Name, Publication Name, 3 Jun. 2004

7
Claro que existe: :%g/^\d\{4}\d\@!/s/^\(\d\{4}\).*\zs/ \1/.
Sato Katsura

Respostas:


17
:% s/\v^(\d{4})(.*)$/\1\2 \1/ 

é uma maneira de fazer isso

  • \v opção mágica, para evitar ter que escapar do agrupamento ()
  • ^ início da linha
  • \d{4} corresponde exatamente a quatro dígitos
  • .* resto da linha
  • \1 \2 tem o padrão correspondente dentro ()

edit: @Jair Lopez menciona nos comentários, a expressão regular pode ser melhorada ainda mais:

:% s/\v^(\d{4}).*/& \1/ 

ou o equivalente

:% s/\v^(\d{4}).*/\0 \1/ 
  • &e \0contém todo o padrão correspondente

Para leitura adicional, vimregex e regex FAQ


3
:%s/\v^(\d{4}).*/& \1/seria um comando mais curto.
Jair López

10

E uma solução com uma macro:

qqyiwA <Esc>pj0q

Que significa:

qq   Record the macro in the register q
yiw  Yank the text described by the text object iw (inner word): The date
A <Esc>   Append a white space to the end of the line and go back to insert mode
p    Paste the date
j0   Place your cursor on the first column of the next line (to be able to repeat the macro)
q    Stop recording

Em seguida, você pode reproduzir a macro quantas vezes quiser 3@a.

Editar Como o @evilsoup mencionou nos comentários, uma maneira mais eficaz de executar a macro em todas as linhas do buffer é usar:

:%normal @q

É claro que você pode substituir %por um intervalo que descreve as linhas a serem modificadas.


3
Você também pode executá-lo em cada linha com:%normal @q
evilsoup

@evilsoup: Obrigado por mencionar isso, vou editar a resposta.
statox

6

Aqui está o caminho que eu faria:

:%norm y4lA <C-o>p

Explicação:

:%norm                     "Apply the following keystrokes to every line:
       y4l                 "Yank 4 letters. You could also do 'yiw'
          A                "Add a space to the end
            <C-o>          "Do a single normal command
                 p         "Paste

4

Se você tiver acesso aos comandos UNIX padrão, poderá usar AWK:

:%!awk '{print $0" "$1}'

Não é realmente vi / vim, então, ou os quatro primeiros caracteres.
pipe

1
Considerar :help filteré um recurso interno do Vim e, considerando como esse recurso permite que o Vim se encaixe no paradigma UNIX, eu diria que é muito vi / vim, na verdade.
Romainl

1

Eu acho que os mecanismos existentes para fazer isso são melhores, mas também é possível fazer isso usando o modo de bloqueio visual .

Copie as datas:

gg          # Go to the top of the file
<ctrl>y     # Enter visual block mode
G           # Go to the bottom of the file
w           # Select the first word
"jy         # Copy in to the j register

Coloque o final da primeira linha:

gg      # Top of file
A       # Append the line
        # Some spaces
<ESC>   # Return to command mode

Colar:

gg 
# Move right to the length of the longest line
"jp   # Paste the block

Note que você só pode fazer 4lem vez dellll
EvergreenTree

@EvergreenTree - Atualizado.
Sixtyfootersdude 25/05

0

Em uma linha de comando unix (ou janelas, se você tiver ferramentas de linha de comando unix instaladas)

sed -e "s/\(....\)\(.*\)/\1\2 \1" < inputFile > outputFile
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.