12

Given a series of lines that look similar to this:

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.

Is there a way that I could grab those first four characters (the year), and copy them to the end of the line, so that it looks like this:

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
1
  • 7
    Sure there is: :%g/^\d\{4}\d\@!/s/^\(\d\{4}\).*\zs/ \1/. May 1, 2016 at 8:06

6 Answers 6

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

is one way to do it

  • \v magic option, to avoid having to escape grouping ()
  • ^ start of line
  • \d{4} match exactly four digits
  • .* rest of line
  • \1 \2 has the matched pattern within ()

edit: @Jair Lopez mentions in comments, the regular expression can be further improved:

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

or the equivalent

:% s/\v^(\d{4}).*/\0 \1/ 
  • & and \0 contains the whole matched pattern

For further reading, vimregex and regex FAQ

1
  • 3
    :%s/\v^(\d{4}).*/& \1/ would be a shorter command. May 1, 2016 at 15:21
11

And a solution with a macro:

qqyiwA <Esc>pj0q

Which means:

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

You can then replay the macro as many time as you have line with 3@a.

Edit As @evilsoup mentioned it in the comments, a more effective way to execute the macro on all the lines of the buffer is to use:

:%normal @q

You can of course replace % by a range describing the lines to modify.

2
  • 3
    You can also execute it on every line with :%normal @q
    – evilsoup
    May 1, 2016 at 9:03
  • @evilsoup: Thanks for mentioning that, I'll edit the answer.
    – statox
    May 1, 2016 at 9:19
6

Here is the way that I would do it:

:%norm y4lA <C-o>p

Explanation:

:%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

If you have access to standard UNIX commands, you could use AWK:

:%!awk '{print $0" "$1}'
2
  • Not really vi/vim, then, or the first four characters.
    – pipe
    May 1, 2016 at 18:04
  • 1
    Considering :help filter is a built-in Vim feature and considering how well that feature allows Vim to fit in the UNIX paradigm I would say it's very vi/vim, actually.
    – romainl
    May 1, 2016 at 18:29
1

I think that the existing mechanisms to do this are better, but it is also possible to do this using visual block mode.

Copy the 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

Pad the end of first line:

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

Paste:

gg 
# Move right to the length of the longest line
"jp   # Paste the block
2
  • Note that you can just do 4l instead of llll May 25, 2016 at 21:40
  • @EvergreenTree - Updated. May 25, 2016 at 21:58
0

From a unix command line (or windows if you have unix command line tools installed)

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.