How to find and replace the first line word with vim - vim

I have a file like this:
foo
bar
And I'm trying to get something like:
foo: foo,
bar: bar,
I've tried :%s/^\w/\0: \0,/g where ^\w matches the first word in line but I'm getting
f: f,foo
b: b,bar
Someone can explain to me what I'm doing wrong?

You are missing two characters (\+) which extend the match to the entire word, because \w only matches one character of a word and not the whole word.
The following should do what you want.
%s/^\w\+/\0: \0,/g

Instead of replacing you could (globally) copy, paste and append:
:g/\v^.+$/normal! yEPa: ^[A,
(where ^[ is escape, entered as <c-v><esc>)
or use (lower-case) e if that is the kind of "word" you want

Related

Match on lines that have one string and NOT another

I am able to match strings in lines of a file like so:
re.search(r"\b10/100/1000\b", line) and re.search(r"notco*", line):
However, I need to be able to match lines that have one string, UNLESS they have another.
Example: Match pattern of '40G' unless the line also contains the pattern 'Po'
just negate the second search:
re.search("40G",line) and not re.search("Po",line)
if no need for regex, then ... no need for regex, use in:
"40G" in line and "Po" not in line

insert n characters before pattern

I have a text file where I want to insert 20 spaces before the string 'LABEL'. I'd like to do this in vim.
I was hoping something like s/LABEL/ {20}LABEL/ would work. It doesn't.
This SO question is close to what I want to do, but I can't put 'LABEL' after the '=repeat()'. Vim regex replace with n characters
%s/LABEL/\=repeat(' ',20)/g works.
%s/LABEL/\=repeat(' ',20)LABEL/g gives me E15: Invalid expression: repeat(' ',20)LABEL
How do I get vim to evaluate =repeat() but not =repeat()LABEL?
After \=, a string is expect. And LABEL isn't a valid string
%s/LABEL/\=repeat(' ',20).'LABEL'/g
BTW thanks to \ze, you don't need to repeat what is searched.
%s/\zeLABEL/\=repeat(' ',20)/g
Note that if you need to align various stuff, you could use printf() instead
%s#label1\|other label#\=printf('%20s', submatch(0))#

vim macro until pattern is matched

I have an array of states that no one is going to have to modify often, so I want to remove the white space.
I tried the following keystrokes as there are some whitespace characters between the commas in the array and the endlines:
q a /, ENTER FORWARD v /\n ENTER d
Unfortunately, whomever formatted this neglected to place any whitespace after 'Montana', so when I run the macro 51#a, it breaks after 27 iterations.
How can I have a macro only run a pattern if \s is matched, or better yet, how can I run a macro until it recognizes ); (end of array).
EDIT: Here is an example. Note the two white space characters after all entries except keys MT,NE,NV and NH.
$state_list = array('AL'=>"Alabama",
'AK'=>"Alaska",
'AZ'=>"Arizona",
'AR'=>"Arkansas",
'CA'=>"California",
'CO'=>"Colorado",
'CT'=>"Connecticut",
'DE'=>"Delaware",
'DC'=>"District Of Columbia",
'FL'=>"Florida",
'GA'=>"Georgia",
'HI'=>"Hawaii",
'ID'=>"Idaho",
'IL'=>"Illinois",
'IN'=>"Indiana",
'IA'=>"Iowa",
'KS'=>"Kansas",
'KY'=>"Kentucky",
'LA'=>"Louisiana",
'ME'=>"Maine",
'MD'=>"Maryland",
'MA'=>"Massachusetts",
'MI'=>"Michigan",
'MN'=>"Minnesota",
'MS'=>"Mississippi",
'MO'=>"Missouri",
'MT'=>"Montana",
'NE'=>"Nebraska",
'NV'=>"Nevada",
'NH'=>"New Hampshire",
'NJ'=>"New Jersey",
'NM'=>"New Mexico",
'NY'=>"New York",
'NC'=>"North Carolina",
'ND'=>"North Dakota",
'OH'=>"Ohio",
'OK'=>"Oklahoma",
'OR'=>"Oregon",
'PA'=>"Pennsylvania",
'RI'=>"Rhode Island",
'SC'=>"South Carolina",
'SD'=>"South Dakota",
'TN'=>"Tennessee",
'TX'=>"Texas",
'UT'=>"Utah",
'VT'=>"Vermont",
'VA'=>"Virginia",
'WA'=>"Washington",
'WV'=>"West Virginia",
'WI'=>"Wisconsin",
'WY'=>"Wyoming"
);
To:
$state_list=array('AL'=>"Alabama",'AK'=>"Alaska",'AZ'=>"Arizona",'AR'=>"Arkansas",'CA'=>"California",'CO'=>"Colorado",'CT'=>"Connecticut",'DE'=>"Delaware",'DC'=>"District Of Columbia",'FL'=>"Florida",'GA'=>"Georgia",'HI'=>"Hawaii",'ID'=>"Idaho",'IL'=>"Illinois",'IN'=>"Indiana",'IA'=>"Iowa",'KS'=>"Kansas",'KY'=>"Kentucky",'LA'=>"Louisiana",'ME'=>"Maine",'MD'=>"Maryland",'MA'=>"Massachusetts",'MI'=>"Michigan",'MN'=>"Minnesota",'MS'=>"Mississippi",'MO'=>"Missouri",'MT'=>"Montana",'NE'=>"Nebraska",'NV'=>"Nevada",'NH'=>"New Hampshire",'NJ'=>"New Jersey",'NM'=>"New Mexico",'NY'=>"New York",'NC'=>"North Carolina",'ND'=>"North Dakota",'OH'=>"Ohio",'OK'=>"Oklahoma",'OR'=>"Oregon",'PA'=>"Pennsylvania",'RI'=>"Rhode Island",'SC'=>"South Carolina",'SD'=>"South Dakota",'TN'=>"Tennessee",'TX'=>"Texas",'UT'=>"Utah",'VT'=>"Vermont",'VA'=>"Virginia",'WA'=>"Washington",'WV'=>"West Virginia",'WI'=>"Wisconsin",'WY'=>"Wyoming");
EDIT:
Just googled vim macro until pattern matched, and came across my own question. I have a better example now:
namespace A{
class a{}
class a{}
}
namespace B{
class b{}
class b{}
class b{}
}
Needs to become:
namespace A{
class Aa{}
class Aa{}
}
namespace B{
class Bb{}
class Bb{}
class Bb{}
}
This cannot be solved with the previously accepted answer.
Honestly the easiest answer would be to join the lines.
If you visual select the entire region and just press J (or feed the range to :join) all of the lines will end up on one line. (There may be excess whitespace in-between elements but thats easier to fix then trying to write the macro).
If you then want to remove the excess whitespace you could run
:s/,\s\+/,/g
on the joined line.
Take a look at :h J and :h :join
First of all, you can easily remove all trailing whitespace with one command:
:%s/\s\+$//e
That will work on every line of the file. If you want to do it only on this fragment of code, you can specify different range (instead of %, which is whole file). For example, you can pass line numbers (1 to 51):
:1,51s/\s\+$//e
or first visually select, and then run command removing whitespace (you have to be on the first line starting this sequence):
V/)<CR>:s/\s\+$//e
If you really want to use macro, you can slightly tweak (and simplify) your macro:
qa0f,lDq
and then run it on every line at once by first of all visually selecting all of them (again, start on line you want, I won't put gg here because it might be just part of the file):
V/)<CR>:normal #q
This will play the macro over every selected line, up to the line with ).
I hope it helps :)

vim macro replacing \n with ','

I am trying to save a macro which replaces \n with ,
Input:
978818
978818
900298
900272
Output:
'978818','978818','900298','900272'
When I saved the macro using CTRL+R CTRL+R,B in vimrc it looks like below:
let #b = ":%s/\n/','/g^MI'^[A~#kb~#kb^["
But now when I run this macro it give the output as:
978818978818900298900272
and error:
E486: Pattern not found: ','
Don't know why it is trying to match ,
You probably need to escape the \n. vim thinks you want a new line character at that point in the string and replaces it with a literal new line. So the fixed macro should be.
let #b = ":%s/\\n/','/g^MI'^[A~#kb~#kb^["
Edit: If you want something that you can copy and paste-able I believe the macro below is equivalent to what you want.
let #b = ":%s/\\n/','/g\nI'\e$xx"

Add a number of '=' in a rest (reStructuredText) document that equals to characters from last line?

I want to use a shortcut to add needed = (from Section/Title reStructuredText syntax) according to the last line.
So, suppose (being | the cursor position)
Title
|
and pressing an specific mapping mapped to a function, add a number of = that equals to the last line (where Title is), becoming:
Title
=====|
This sequence will get you close:
kyyp:.s/./=/g
Duplicate the previous line, then in that line, change every character to an equals sign. Map that to a key sequence you like, and try it out.
Another way:
:execute "normal " . strlen(getline(line(".") - 1)) . "i="
strlen(getline(line(".") - 1)) returns the lenght of the line above the current position. The result is that the command Ni= is executed, inserting = N times.
For a mapping I would have used:
put=repeat('=', col('$')-1)
For something more interactive, I would have use the same solution as Ned's.
(I don't like my mappings to change the various registers like #" or #/)
My vim-rst-sections vim plugin will convert lines to section headings:
http://www.vim.org/scripts/script.php?script_id=4486
In your case, you'd put the cursor on the line, and type <leader><leader>d to get a top-level heading like this:
#####
Title
#####
A few repeats of <leader><leader>d will take you down to the standard hierarchy of Python ReST sections to the =.

Resources