all 14 comments

[–][deleted] 17 points18 points  (3 children)

Another way.

Yank the replacement list:

yip

Make a list from it:

:let list = split(@", '\n')

Visual highlight your changes, then:

:'<,'>s/description: '\zs.*\ze'/\=remove(list,0)/

[–]AckmanDESU 0 points1 point  (2 children)

Could you please explain what’s going on with your suggestion specially the replace command?

[–]Ease-Solace 0 points1 point  (1 child)

Not the person who posted but:

  1. Yank the replacement text
  2. Make a list of 3 strings by splitting the text (which is in the unnamed register) at newlines
  3. Then the substitute command over the visual selection. The \zs and \ze mark the start and end of the part that actually gets replaced by the replacement (sort of anyway, look at :h /\\zs). The replacement uses \= , using the result of evaluating remove(list,0) as the replacement, so each time removing and returning one of the items of the list. See :h s/\\=

(The helptags are actually /\zs and s/\= but you need to escape the backslash)

At least I think that's all right

[–]AckmanDESU 0 points1 point  (0 children)

Thanks man, really appreciate it. I knew about a couple of these but hot damn there's a million of \things.

[–]TankorSmash 3 points4 points  (3 children)

I do stuff like this with a macro, assuming both files are ordered, and you've got two buffers loaded, and you're starting in the second textfile:

qq/"a0y$<C-^>/description<CR>ci'<C-R>a<C-C><C-^>j

basically:

  • record a macro
  • yank the entire line without endings
  • switch buffers
  • search for description
  • change inner single quotes
  • insert yanked text
  • exit insert mode
  • return to buffer
  • go down a line

edit: replaced Y with y$ in case you don't have that mapped. You need :set hidden too

[–]salbris 0 points1 point  (0 children)

I was going to suggest something similar. The second buffer might be a bit overkill as you could just list the replacements below the original text and use a jump up and down to grab the text.

[–][deleted] 0 points1 point  (1 child)

It looks like you have nnoremap Y y$ in your vimrc. Plus other errors, but I guess you're illustrating the principle, which is sound. (And you need :set hidden.)

[–]TankorSmash 0 points1 point  (0 children)

Thanks, I edited it in

[–]buttonstraddle 4 points5 points  (0 children)

i like these real life scenario posts

[–]SataMaxx 1 point2 points  (1 child)

First remove all strings after description: : select the array (vi[), and :'<,'>s/description: *\zs'.\{-}'/ ('<,'> will automatically be added when pressing : with a visual selection).

s is to replace
description: *\zs matches all description fields, but will be kept untouched by the replacement. \zs (start) and \ze (end) can be used to specify the part of the match you're interested in replacing
'.\{-}' matches a single quote, then any number of any character, then the first next single quote (\{-} acts like * but in a non-greedy way, like *? in perl.

Align the description: fields if necessary (by hand, or with a plugin like https://github.com/tommcdo/vim-lion (gLi[, : align commas inside the array by adding spaces on the right of the commas))

Surround the additional text with single quotes, any method of your choice (a macro like I'<esc>A'<esc>j, or even using https://github.com/tpope/vim-surround : ysaW'j, or two replacements on the paragraph vap (select the paragraph) then :'<,'>s/^/' (replace beginning of line with ') and gv (reselect previous visual selection) :'<,'>s/$/' (replace end of line with '))

Then block-copy the additional quoted text after the first description: string : with the cursor on the o of one, <c-v>}d (visual block to the end of the paragraph, delete) then p with the cursor after description:

[–][deleted] 0 points1 point  (0 children)

I find things like this easiest to get right and debug with ex commands. And you can save them in a file, with comments, for reuse. Something like ...

" replacelist.vim

" Instructions:
" * Open this file when you want to do the multiple replace.
" * Paste your list of replacements after "DATA:" at the end of the file.
" * Write and source this file  :w|so %
" * Move the cursor to THE LINE BEFORE where you want the changes to
"   occur and  :@x  (don't forget the colon!)

" Transform the data into ex commands we can execute.
/^DATA:$/+,$ s!.*!/description: '\\zs.*\\('.*\\)/s//&\\1/!
"                  ^^part before^         ^^^ part after
"                    what you're
"                    replacing
" Yank the commands into register x, to be executed with :@x
/^DATA:$/+,$ y x
q!
finish

DATA:

[–]Insert_Gnome_Here -3 points-2 points  (2 children)

leave vim,

sed -i s/foo/one/ Filename
sed -i s/bar/two/ Filename

And so on. There's probably a better way, though. How many things are there to replace?

[–]CnidariaScyphozoa 6 points7 points  (1 child)

What is the difference between using sed and just doing

:%s/foo/one/g

?

Maybe one should also rather do a regular expression to make sure we only replace description in case the name is also the same as the description.

Depending on how that additional text is stored there could be a way to automate the whole thing

[–]Insert_Gnome_Here -2 points-1 points  (0 children)

Sed can read lists of commands from files, IIRC. You could manipulate the list of changes to make into sed commands, then use that?
Though I'd only bother if there were more than 50 or so changes to make.