18

Assuming I have a line in a file with XXXX being a placeholder I have selected via v as follows:

XXXX Some other text

How can I change only the XXXX with the output of an external command, such as date +%Y%m%d?

I got as far as

:'<,'>!date +\%Y\%m\%d 

but that replaced the whole line.

1

5 Answers 5

18

You could delete the text and insert the output of a command using CtrlR-=:

CTRL-R {0-9a-z"%#*+:.-=}                                        i_CTRL-R
                Insert the contents of a register.  Between typing CTRL-R and
                the second character, '"' will be displayed to indicate that
                you are expected to enter the name of a register.
 …
                                                        i_CTRL-R_=
                        '='     the expression register: you are prompted to
                                enter an expression (see expression)

For the expression, you can use the system() function to run external commands.

After selecting the text, press c, then <c-r>= and use system('date +%Y%m%d') as the expression.

4
  • 1
    That adds a newline between the replaced text and the rest of the line, doesn't it?
    – muk.li
    Commented Apr 17, 2016 at 20:10
  • 2
    @muk.li that's part of the output of date. If you try something like system('printf %s foo'), which doesn't output a trailing newline, you'll see there's a difference.
    – muru
    Commented Apr 17, 2016 at 20:12
  • 5
    @muk.li if you just want the date in the text, there's the strftime function which you can use instead of system('date …'). The format string is the same.
    – muru
    Commented Apr 17, 2016 at 20:27
  • 4
    You do not need to delete selected text. You can use "=system('date +%Y%m%d')p on visual selection instead.
    – Hauleth
    Commented Apr 18, 2016 at 8:03
5

If you put the cursor on such a line you can:

  • 0 to put the cursor in the first column.
  • f Space to put the cursor in the first blank.
  • i Enter Esc to split the line.
  • l to move the cursor one line up.
  • :.!date +\%Y\%m\%d to execute the command.
  • J to join the lines again.

From :h :visual_example:

Currently the ":" command works on whole lines only. When you select part of a line, doing something like ":!date" will replace the whole line. If you want only part of the line to be replaced you will have to make a mapping for it. In a future release ":" may work on partial lines.

See also :h visual-operators for details.

From this comment: You can also try the vis or NrrwRgn plugin. Both should handle it just fine. (Thanks @christian-brabandt for the tip).

2

Create a temporary mapping for such replacements. For example:

:vnoremap qq c<C-R>=system('wc -c | perl -pe chomp', @")<CR><ESC>

Then in visual mode you can select text, type qq and it'll be replaced by the command output. In this example wc -c will process your selection, which is the @" parameter. perl -pe chomp is needed to remove a trailing newline from the output.

1
  • 1
    Note that this solution is a wrapper around muru's answer, creating a mapping for a one time usage might not be the most efficient method.
    – statox
    Commented Nov 13, 2018 at 16:06
1

Try this:

:let @a = system('date +\%Y\%m\%d')[:-2]
:'<,'>g/XXXX/s/XXXX/\=@a/g
  • The first line saves the output of date command into register a, with the ending newline removed.
  • The second line globally inspect your selection and mark the lines containing XXXX (g/XXXX/), and
  • replace all the instances of the XXXX with the content of register a (s/XXXX/\=@a/g)

See :h let-@ and :h :global as well as the "Sublist" section in :h list-index

0

Plugin: Visual Block Commands (vis) by DrChip

Installation of vis.vba.gz and dependency cecutil.vba.gz into vim8 packpath

# shell brace expansion (bash >=3.0, zsh>=2.6)
$ mkdir -p ~/.vim/pack/manual/start/{vis,cecutil}
$ vim http://www.drchip.org/astronaut/vim/vbafiles/vis.vba.gz
:UseVimball ~/.vim/pack/manual/start/vis
:e http://www.drchip.org/astronaut/vim/vbafiles/cecutil.vba.gz
:UseVimball ~/.vim/pack/manual/start/cecutil

OP example becomes

:'<,'>B !date +\%Y\%m\%d 

Your Answer

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

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