¿Cómo copiar los primeros cuatro caracteres de cada línea al final de esa misma línea?

10

Dada una serie de líneas que se parecen a esto:

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.

¿Hay alguna manera de que pueda tomar esos primeros cuatro caracteres (el año) y copiarlos al final de la línea, para que se vea así:

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
mezcla
fuente
77
Seguro que hay: :%g/^\d\{4}\d\@!/s/^\(\d\{4}\).*\zs/ \1/.
Sato Katsura

Respuestas:

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

es una forma de hacerlo

  • \v opción mágica, para evitar tener que escapar de la agrupación ()
  • ^ inicio de línea
  • \d{4} coincidir exactamente con cuatro dígitos
  • .* resto de línea
  • \1 \2 tiene el patrón combinado dentro ()

editar: @Jair Lopez menciona en los comentarios, la expresión regular se puede mejorar aún más:

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

o el equivalente

:% s/\v^(\d{4}).*/\0 \1/ 
  • &y \0contiene todo el patrón combinado

Para leer más, vimregex y regex FAQ

Sundeep
fuente
3
:%s/\v^(\d{4}).*/& \1/Sería un comando más corto.
Jair López
10

Y una solución con una macro:

qqyiwA <Esc>pj0q

Lo 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

Luego puede reproducir la macro tantas veces como tenga una línea 3@a.

Editar Como @evilsoup lo mencionó en los comentarios, una forma más efectiva de ejecutar la macro en todas las líneas del búfer es usar:

:%normal @q

Por supuesto, puede reemplazarlo %por un rango que describa las líneas a modificar.

statox
fuente
3
También puede ejecutarlo en cada línea con:%normal @q
evilsoup
@evilsoup: Gracias por mencionar eso, editaré la respuesta.
statox
6

Aquí está la forma en que lo haría:

:%norm y4lA <C-o>p

Explicación:

:%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
James
fuente
4

Si tiene acceso a comandos UNIX estándar, puede usar AWK:

:%!awk '{print $0" "$1}'
romainl
fuente
No realmente vi / vim, entonces, o los primeros cuatro caracteres.
tubería
1
Considerar :help filteres una función incorporada de Vim y considerando cuán bien esa característica le permite a Vim encajar en el paradigma de UNIX, diría que es muy vi / vim, en realidad.
romainl
1

Creo que los mecanismos existentes para hacer esto son mejores, pero también es posible hacerlo usando el modo de bloque visual .

Copia las fechas:

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

Rellene el final de la primera línea:

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

Pegar:

gg 
# Move right to the length of the longest line
"jp   # Paste the block
Sixtyfootersdude
fuente
Tenga en cuenta que puede hacerlo en 4llugar dellll
EvergreenTree
@EvergreenTree - Actualizado.
sixtyfootersdude
0

Desde una línea de comandos de Unix (o Windows si tiene instaladas herramientas de línea de comandos de Unix)

sed -e "s/\(....\)\(.*\)/\1\2 \1" < inputFile > outputFile
Itsme2003
fuente