10

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

| improve this answer | |
  • 3
    :%s/\v^(\d{4}).*/& \1/ would be a shorter command. – Jair López May 1 '16 at 15:21
10

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.

| improve this answer | |
  • 3
    You can also execute it on every line with :%normal @q – evilsoup May 1 '16 at 9:03
  • @evilsoup: Thanks for mentioning that, I'll edit the answer. – statox May 1 '16 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
| improve this answer | |
4

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

:%!awk '{print $0" "$1}'
| improve this answer | |
  • Not really vi/vim, then, or the first four characters. – pipe May 1 '16 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 '16 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
| improve this answer | |
  • Note that you can just do 4l instead of llll – EvergreenTree May 25 '16 at 21:40
  • @EvergreenTree - Updated. – sixtyfootersdude May 25 '16 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
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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