Comment copier les quatre premiers caractères de chaque ligne à la fin de cette même ligne?

10

Étant donné une série de lignes qui ressemblent à ceci:

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-t-il un moyen de saisir ces quatre premiers caractères (l'année) et de les copier à la fin de la ligne, pour que cela ressemble à ceci:

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
mélanger
la source
7
Bien sûr , il y a: :%g/^\d\{4}\d\@!/s/^\(\d\{4}\).*\zs/ \1/.
Sato Katsura

Réponses:

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

est une façon de le faire

  • \v option magique, pour éviter d'avoir à échapper au groupement ()
  • ^ début de ligne
  • \d{4} correspondre exactement à quatre chiffres
  • .* reste de ligne
  • \1 \2 a le modèle correspondant dans ()

edit: @Jair Lopez mentionne dans les commentaires, l'expression régulière peut être encore améliorée:

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

ou l'équivalent

:% s/\v^(\d{4}).*/\0 \1/ 
  • &et \0contient tout le motif assorti

Pour plus de lecture, FAQ vimregex et regex

Sundeep
la source
3
:%s/\v^(\d{4}).*/& \1/serait une commande plus courte.
Jair López
10

Et une solution avec une macro:

qqyiwA <Esc>pj0q

Ce qui signifie:

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

Vous pouvez ensuite rejouer la macro autant de fois que vous le souhaitez 3@a.

Modifier Comme @evilsoup l'a mentionné dans les commentaires, un moyen plus efficace d'exécuter la macro sur toutes les lignes du tampon est d'utiliser:

:%normal @q

Vous pouvez bien sûr le remplacer %par une plage décrivant les lignes à modifier.

statox
la source
3
Vous pouvez également l'exécuter sur chaque ligne avec:%normal @q
evilsoup
@evilsoup: Merci d'avoir mentionné cela, je vais modifier la réponse.
statox
6

Voici la façon dont je le ferais:

:%norm y4lA <C-o>p

Explication:

:%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
la source
4

Si vous avez accès aux commandes UNIX standard, vous pouvez utiliser AWK:

:%!awk '{print $0" "$1}'
romainl
la source
Pas vraiment vi / vim, alors, ni les quatre premiers caractères.
pipe
1
Considérant que :help filterc'est une fonctionnalité Vim intégrée et considérant à quel point cette fonctionnalité permet à Vim de s'intégrer dans le paradigme UNIX, je dirais que c'est très vi / vim, en fait.
romainl
1

Je pense que les mécanismes existants pour ce faire sont meilleurs, mais il est également possible de le faire en utilisant le mode bloc visuel .

Copiez les dates:

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

Remplissez la fin de la première ligne:

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

Pâte:

gg 
# Move right to the length of the longest line
"jp   # Paste the block
sixtyfootersdude
la source
Notez que vous pouvez simplement faire à la 4lplace dellll
EvergreenTree
@EvergreenTree - Mis à jour.
sixtyfootersdude
0

Depuis une ligne de commande Unix (ou Windows si vous avez installé des outils de ligne de commande Unix)

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