replacing brackets - regex

I would like to replace all occurrences of "exp( ... )" with "Exp[ ... ]" in the following (essentially changing from Matlab to Mathematica syntax):
exp(-(pi*k2*2i)/3)*(v9/4 + (3^(1/2)*(v8/2 + (3^(1/2)*v9)/2))/2 + (3^(1/2)*v8)/12) + exp((pi*k2*2i)/3)*(v9/4 + (3^(1/2)*(v8/2 + (3^(1/2)*v9)/2))/2 + (3^(1/2)*v8)/12) ...
Is it possible to automate this with vim, sed, or awk? The trick is not replacing all "(" with "[", only the ones that occur immediately after exp and the corresponding pair.

You can do that with a vim macro.
Let's clear the a register by pressing qaq. ( In case if any previous operations are recorded, we can clear them)
Start a macro recording by pressing qa.
Search for exp( by typing/exp(/e. this will put the cursor at (.
Press % to move to its closing bracket. Press r] to replace it with ].
Now, press N to move to exp(. Press r[ to replace it with [. Press #a to recursively replace all such instances. Press q to stop recording.
Now, you can press#a to play the macro and it will replace everywhere.

In the following sed script (brackreplace) we are:
exp( → Exp§
hide balanced (...) → «...» (if they have no "()§" inside)
Exp§...) → Exp[...]
restoring hidden parentesis
#!/bin/sed -zf
s/exp(/Exp§/g # (1) protect exp( → Exp§
s/(\([^()§]*\))/«\1»/g # (2) hide balanced (...) → «...»
s/Exp§\([^()§]*\))/Exp[\1]/g # (3) Exp§...) → Exp[...]
s/«/(/g # restore protected parentesis
s/»/)/g
This cover your example; repeat line (2) if you expect deeper () inside exp(...).
After chmod, this command may be used in command line or inside the editor. Example with vim:
:%!bracketreplace

Just like Sibi's answer, but just a subtle change, you should use `` to jump back to the matching brace instead of N. otherwise it doesn't work with this pattern: exp(...exp(...))

Related

CSS add missing semicolons in Vim via regex

I'm cleaning up some CSS for our company and in many of the classes there are missing semicolons. I've tried a number of different ways to make this happen in Vim, but so far I haven't found a viable solution. Below is an example of one class that seems to be part of a theme in this file.
What I'm thinking... if there's a \w \s \{ || \w\; then don't return true. Otherwise if there's a \:\s\w and no ; at the end of a line then return true.
.ribbon_table,
.tabbed_interface_section_table,
table#monthview_table,
table#weekview_table_table {
border-collapse: collapse
}
.btn.active.focus,
.btn.active:focus,
.btn.focus,
.btn:active.focus,
.btn:active:focus,
.btn:focus,
a:focus,
button:focus,
form:focus,
input:focus,
select:focus,
textarea:focus {
outline: 0;
}
blockquote {
font-size: 14px;
border: 0;
}
.caret {
border-top-style: solid
}
I would do something like :g/\v^\s+\S+:.+[^;]$/norm A;.
In case you're unfamiliar with these commands, here's the vim documentation for :g (:global) and :norm (:normal).
:g :global E147 E148
:[range]g[lobal]/{pattern}/[cmd]
Execute the Ex command [cmd] (default ":p") on the
lines within [range] where {pattern} matches.
:norm[al][!] {commands} :norm :normal
Execute Normal mode commands {commands}. This makes
it possible to execute Normal mode commands typed on
the command-line. {commands} are executed like they
are typed. For undo all commands are undone together.
Execution stops when an error is encountered.
If the [!] is given, mappings will not be used.
Without it, when this command is called from a
non-remappable mapping (:noremap), the argument can
be mapped anyway.
{commands} should be a complete command. If
{commands} does not finish a command, the last one
will be aborted as if <Esc> or <C-C> was typed.
This implies that an insert command must be completed
(to start Insert mode, see :startinsert). A ":"
command must be completed as well. And you can't use
"Q" or "gQ" to start Ex mode.
The display is not updated while ":normal" is busy.
{commands} cannot start with a space. Put a count of
1 (one) before it, "1 " is one space.
The 'insertmode' option is ignored for {commands}.
This command cannot be followed by another command,
since any '|' is considered part of the command.
This command can be used recursively, but the depth is
limited by 'maxmapdepth'.
An alternative is to use :execute, which uses an
expression as argument. This allows the use of
printable characters to represent special characters.
Example:
:exe "normal \<c-w>\<c-w>"
On the example you gave, :%s/\(\w*:\s*\w*\)$/\1; works fine.
Since it is not very readable, let's add some details:
Look for a word \w*
Followed by a :
Followed by between 0 and n spaces \s*
Followed by a word \w*
Followed by the end of a line $
You save this whole expression (let's call it expr) using parenthesis \(expr\), and use it again in the second hand using \1.
Thus, you can add the missing ; using \1;.

How to convert vector at access to operator [ ] access in vim

Suppose I want to convert
var.at(i*w+j) = something;
into
var[i*w+j] = something;
What is the correct command to type in vim? I attempted
:%s/\.at\(.*\)/[\1]/g
which results in
var[(i*w+j) = something;]
works but it will be even better if the parentheses can be removed.
EDIT: showing correct resulting attempt
With a recursive macro:
qqqqq/\.at(<CR>%"adi)F.c%[<Esc>"apa]<Esc>#qq#q
Explanation:
qq record macro `q`
q end empty macro
qq record macro `q`
/\.at(<CR> search for `.at(`
% go to the matching closing `)`
"adi) delete inside the parenthesis into register `a`
F. go back to the previous `.`
c% change what’s in the matching parenthesis
[<Esc> with `[` and leave insert mode
"ap paste what’s in register `a`
a]<Esc> append `]` and leave insert mode
#q call the (currently empty) `q` macro recursively
q end macro
#q call the (now non-empty) macro `q`
This also handle stuff like var.at(foo(bar, baz)) = something; correctly.
What is the correct command to type in vim? I attempted
:%s/\.at\(.*\)/[\1]/g
The problem is that you're escaping the parens. Due to your "magic" settings, \( and \) work for grouping, whereas you want to match literal ( and )
:%s/\.at(\(.*\))/[\1]/g
works for me. (Note that you still need the grouping)

Enumerate existing text in Vim (make numbered list out of existing text)

I have a source document with the following text
Here is a bunch of text
...
Collect underpants
???
Profit!
...
More text
I would like to visually select the middle three lines and insert numbers in front of them:
Here is a bunch of text
...
1. Collect underpants
2. ???
3. Profit!
...
More text
All the solutions I found either put the numbers on their own new lines or prepended the actual line of the file.
How can I prepend a range of numbers to existing lines, starting with 1?
It makes for a good macro.
Add the first number to your line, and put your cursor back at the beginning.
Start a macro with qq (or q<any letter>)
Copy the number with yf<space> (yank find )
Move down a line with j
Paste your yank with P
Move back to the beginning of the line with 0
Increment the number with Ctrl-a
Back to the beginning again with 0 (incrementing positions you at the end of the number)
End the macro by typing q again
Play the macro with #q (or #<the letter you picked>)
Replay the macro as many times as you want with <number>## (## replays the last macro)
Profit!
To summarize the fun way, this GIF image is i1. <Esc>0qqyf jP0^a0q10#q.
To apply enumeration for all lines:
:let i=1 | g/^/s//\=i.'. '/ | let i=i+1
To enumerate only selected lines:
:let i=1 | '<,'>g/^/s//\=i.'. '/ | let i=i+1
Set non recursive mapping with following command and type ,enum in command mode when cursor is inside the lines you are going to enumerate.
:nn ,enum {j<C-v>}kI0. <Esc>vipg<C-a>
TL;DR
You can type :help CTRL-A to see an answer on your question.
{Visual}g CTRL-A Add [count] to the number or alphabetic character in
the highlighted text. If several lines are
highlighted, each one will be incremented by an
additional [count] (so effectively creating a
[count] incrementing sequence).
For Example, if you have this list of numbers:
1.
1.
1.
1.
Move to the second "1." and Visually select three
lines, pressing g CTRL-A results in:
1.
2.
3.
4.
If you have a paragraph (:help paragraph) you can select it (look at :help object-select). Suppose each new line in the paragraph needs to be enumerated.
{ jump to the beginning of current paragraph
j skip blank line, move one line down
<C-v> emulates Ctrl-v, turns on Visual mode
} jump to the end of current paragraph
k skip blank line, move one line up
required region selected, we can make multi row edit:
I go into Insert mode and place cursor in the beginning of each line
0. is added in the beginning of each line
<Esc> to change mode back to Normal
You should get list prepended with zeros. If you already have such, you can omit this part.
vip select inner paragraph (list prepended with "0. ")
g<C-a> does the magic
I have found it easier to enumerate with zeroes instead of omitting first line of the list to enumerate as said in documentation.
Note: personally I have no mappings. It is easier to remember what g <C-a> does and use it directly. Answer above describes usage of pure <C-a> which requires you to manually count whatever, on the other hand g <C-a> can increment numbers with given value (aka step) and have it's "internal counter".
Create a map for #DmitrySandalov solution:
vnoremap <silent> <Leader>n :<C-U>let i=1 \| '<,'>g/^/s//\=i.'. '/ \| let i=i+1 \| nohl<CR>

In Vim, is there a "matching braces/parenthesis/etc" equivalent in substitute/search symbols?

I would like to replace for instance every occurrence of "foo{...}" with anything except newlines inside the bracket (there may be spaces, other brackets opened AND closed, etc) NOT followed by "bar".
For instance, the "foo{{ }}" in "foo{{ }}, bar" would match but not "foo{hello{}}bar".
I've tried /foo{.*}\(bar\)\#! and /foo{.\{-}}\(bar\)\#! but the first one would match "foo{}bar{}" and the second would match "foo{{}}bar" (only the "foo{{}" part).
this regex:
foo{.*}\([}]*bar\)\#!
matches:
foo{{ }}
foo{{ }}, bar
but not:
foo{hello{}}bar
It is impossible to correctly match an arbitrary level of nested
parentheses using regular expressions. However, it is possible to
construct a regex to match supporting a limited amount of nesting (I
think this answer did not attempt to do so). – Ben
This does ...
for up to one level of inner braces:
/foo{[^{}]*\({[^{}]*}[^{}]*\)*}\(bar\)\#!
for up to two levels of inner braces:
/foo{[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}\(bar\)\#!
for up to three levels of inner braces:
/foo{[^{}]*\({[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}[^{}]*\)*}\(bar\)\#!
...
Depends on what replacement you want to perform exactly, you might be able to do that with macros.
For example: Given this text
line 1 -- -- -- -- array[a][b[1]]
line 2 -- array[c][d]
line 3 -- -- -- -- -- -- -- array[e[0]][f] + array[g[0]][h[0]]
replace array[A][B] with get(A, B).
To do that:
Position the cursor at the begin of the text
/array<cr>
qq to begin recording a macro
Do something to change the data independent of the content inside (use % to go to matching bracket, and some register/mark/plugin to delete around the bracket). For example cwget(<esc>ldi[vhpa, <esc>ldi[vhpa)<esc>n -- but macros are usually unreadable.
n to go to next match, q to stop recording
#q repeatedly (## can be used from the second time)
This is probably not very convenient because it's easy to make a mistake (press I, <home>, A for example) and you have to redo the macro from the beginning, but it works.
Alternatively, you can do something similar to eregex.vim plugin to extend vim's regex format to support this (so you don't have to retype the huge regex every time).
Proof of concept:
"does not handle different magic levels
"does not handle '\/' or different characters for substitution ('s#a#b#')
"does not handle brackets inside strings
" usage: `:M/pattern, use \zm for matching block/replacement/flags`
command -range -nargs=* M :call SubstituteWithMatching(<q-args>, <line1>, <line2>)
":M/ inspired from eregex.vim
function SubstituteWithMatching(command, line1, line2)
let EscapeRegex={pattern->escape(pattern, '[]\')}
let openbracket ='([{'
let closebracket=')]}'
let nonbracketR='[^'.EscapeRegex(openbracket.closebracket).']'
let nonbracketsR=nonbracketR.'*'
let LiftLevel={pattern->
\nonbracketsR
\.'\%('
\.'['.EscapeRegex(openbracket).']'
\.pattern
\.'['.EscapeRegex(closebracket).']'
\.nonbracketsR
\.'\)*'
\}
let matchingR=LiftLevel(LiftLevel(LiftLevel(nonbracketsR)))
if v:false " optional test suite
echo "return 0:"
echo match('abc', '^'.matchingR.'$')
echo match('abc(ab)de', '^'.matchingR.'$')
echo match('abc(ab)d(e)f', '^'.matchingR.'$')
echo match('abc(a[x]b)d(e)f', '^'.matchingR.'$')
echo match('abc(a]b', '^'.matchingR.'$')
"current flaw (not a problem if there's only one type of bracket, or if
"the code is well-formed)
echo "return -1:"
echo match('abc(a(b', '^'.matchingR.'$')
echo match('abc)a(b', '^'.matchingR.'$')
endif
let [pattern, replacement, flags]=split(a:command, "/")
let pattern=substitute(pattern, '\\zm', EscapeRegex(matchingR), 'g')
execute a:line1.','.a:line2.'s/'.pattern.'/'.replacement.'/'.flags
endfunction
After this, :'<,'>M/array\[\(\zm\)\]\[\(\zm\)\]/get(\1, \2)/g can be used to do the same task above (after selecting the text in visual mode)

Rewriting C macro code with VIM search & replace

I've got a file that uses an outdated macro to read 32 bit integers,
READ32(dest, src)
I need to replace all calls with
dest = readUint32(&src);
I'm trying to write a SED style Vim search & replace command, but not having luck.
I can match the 1st part using READ32([a-z]\+, cmd) using the / search prompt, but it does not seem to match in the :s syntax.
Here's what I finally figured out to work:
:%s/READ32(\(\a\+\),\(\a\+\)/\1 = readUint32(\&\2);
The trick is wrapping the values you want to store in \1 & \2 in \( and \) The other trick was you have to escape the & operator as & in vim replacement is "the whole match".
EDIT: improved further as I refined it:
:%s/READ32(\(\w\+\),\s*\(\w\+\)/\1 = readUint32(\&\2);
Changed \a to \w as I had variables with _ in them.
Added \s* to take care of white space issues between the , and second variable.
Now just trying to deal with c++ style variables of style class.variable.subvariable
EDIT 2:
replaced \w with [a-zA-Z0-9_.] to catch all of the ways my variables were named.
This should do what you want or at least get you started:
%s-READ32(\s*\(\i\+\)\s*,\s*\(\i\+\)\s*)-\1 = readUint32(\&\2);-g
I'd do the macro style again: hit * to 'highlight' search for READ32.
Now, we are going to record a macro (q..qq):
n (move to next match)
cwreadUint32Esc (change the function name)
wwdt, (delete the first argument)
"_dw (remove the redundant ,)
bbPa=Esc (insert the result variable appending = before readUint32)
A; (append ; to the end of the line)
Now you can just repeat the macro (1000#q).