Vim: remove matching braces and the first word in the braces - regex

For example, change
text 12345 {\color{red}text 123 \ref{label} 567
1234} 567
to
text 12345 text 123 \ref{label} 567
1234 567
What kind of operation should be done in vim?
I aim to find every all patterns {\color{red}
and remove the pattern and the matching brace } for the pattern,
while keeping the text in between.
The pattern {\color{red} can be anywhere in the line (not necessarily at the beginning of the line).
The text between the {\color{red} ...} can have multiple lines as shown above.
Thanks a lot for your help.
Edit:
I just find a way to do it, but may not be efficient enough.
:g/\\color{red}/norm ndiBvaBpd%
g: global
/\\color{red}: match the pattern
/norm: normal mode command
n: forward the cursor to next matching pattern from the cursor. But if the pattern is at the beginning of the line, it may fail to find it.
diB: delete inner block from the cursor
vaB: select block around the cursor
p: put to the selected block
d%: delete \color{red}

didn't get what do you really mean. there are many ways could do it.
{\color{red}text 123 \ref{label} 567}
^
|cursor
you could do:
df}$x
if you have surround.vim installed, removing surrounding braces would be easier. (ds{)
EDIT
for the question update:
open your file, and type:
:g#{\\color{red}#normal 0df}$x
hope the command does what you want.
EDIT II based on question update
if your target text object is crossing lines, you could try this:
g/{\\color{red}/normal 0f{mz%x`zxdf}
above line works if your target pattern crossing multiple lines (not only one/two, could be many). However the syntax must be correct, which means, the { , } must be paired.

I would use a substitution with regex for this:
%s/\v\{\\color\{\w+\}(.*)} ?$/\1
\v very magic (sane regexes)
{\\color\{\w+\} the color thingy
(.*) capture the text you want to save
} ?$ closing nipple bracket and optional space at the end of the line
/\1 replace the whole thing with the first capture, which is stuff between color tag BS
For your edited example, you can use \_. instead of . because it includes linebreak characters.
%s/\v\{\\color\{\w+\}(\_.*)}/\1

Related

How can I delete this part of the text with regex?

I have a problem that I really hope that somebody could help me. So, I want to delete some parts of text from a notepad++ document using Regex. If there's another software that I can use to delete this part of text, let me know please, I am really really noob with regex
So, my document its like this:
1
00:00:00,859 --> 00:00:03,070
text over here
2
00:00:03,070 --> 00:00:09,589
text over here
3
00:00:09,589 --> 00:00:10,589
some numbers here
4
00:00:10,589 --> 00:00:12,709
Text over here
5
00:00:12,709 --> 00:00:18,610
More text with numbers here
What I want to learn is how can I delete the first 2 lines of numbers in all the document? So I could get only the text parts (the "text over here" parts)
I would really appreciate any kind of help!
My solution:
^[\s\S]{1,5}\d{1,3}:\d{1,3}:\d{1,3},\d{1,5}\s-->\s*?\d{1,3}:\d{1,3}:\d{1,3},\d{1,5}\s
This solution match both types: either all data in one line, or numbers in one line and data in the second.
Demo: https://regex101.com/r/nKD0DQ/1/
Simplest solution;
\d+(\r\n|\r|\n)\d{2}:\d{2}.*(\r\n|\r|\n)
Get line with some number \d+ with its line break (\r\n|\r|\n)
Also the next line that starts with two 2-digit numbers and a colon \d{2}:\d{2} with the rest .* and its line break. No need to match all since we already are in the correct line, since subtitle file is defined well with its predictable structure.
Put this as Find what: value in Search -> Replace.. in Notepad++, with Seach Mode: Regular Expression and with replace value (Replace with:) of empty space. Will get you the correct result, lines of expected text with empty line in between each.
to see it on action on regex101
Subtitles, for accuracy you can use this:
\d+(\r\n|\n|\r)(\d\d:){2}\d\d,\d{3}\s*-->\s*(\d\d:){2}\d\d,\d{3}(\r\n|\n|\r)
Check Regular Expression, Find what with this and Replace with empty would do.
Regxe Demo
srt subtitles are basically ordered. And it's better accurate than lose texts.
\d : a single digit.
+ : one or more of occurances of the afore character or group.
\r\n: carriage and return. (newline)
* : zero or more of occurances of the afore character or group.
| : Or, match either one.
{3}: Match afore character or group three times.
I'm going for a less specific regex:
^[0-9]*\n[0-9:,]*\s-->\s[0-9:,]*
Demo # regex101

Notepad++ and regex (multiline)

I have been facing a challenge. I have a text file with the following pattern:
SOME RANDOM TITLE IN CAPS (nnnn)
text text text
more text
...
SOME OTHER RANDOM TITLE IN CAPS (nnnn)
What is for sure is that what I want to extract are lines with a bracket and a date ex: (2015) ; (20008)
After the (nnnn) there is no text, sometimes space and CR LF, sometimes just CR LF
I would like to delete everything else and keep just the TITLE LINE with the brackets
The time I spent I could have done it by hand (there are 100lines) but I like the challenge :)
I thought I could find the issue but I am stuck.
I have tried something along this line:
^.*\(\d\d\d\d\)(?s)(.*)(^.*\(\d\d\d\d\))
But I don't get what I want. I can't seem to stop the (?s)(.*) going all the way to the end of the text instead of stopping at the next occurrence.
I suggest using the Search > Mark feature. Use a pattern like \(\d{4}\) and check the "Bookmark Line" option then click "Mark All". Then use Search > Bookmark > Remove Unmarked Lines. This will remove all lines except the ones that have matched your pattern.
Note: If it's possible to have parentheses with 4 digits within your other lines you could add $ to the end of the expression to ensure that the pattern only matches the end of the line. E.g. more text (1234) and other stuff would be matched by the pattern I gave above but if you use pattern \(\d{4}\)$ it will no longer match.
If you want to be even more specific with your pattern by looking for those lines with only uppercase letters and spaces followed by parentheses with 4 digits inside where the parentheses are at the end of the line, then you could use a pattern like this: [A-Z ]+\(\d{4}\)$
Sample input:
SOME RANDOM TITLE IN CAPS (2008)
text text text
more text
...
SOME OTHER RANDOM TITLE IN CAPS (2010)
Here is how to mark the lines:
After clicking "Mark All" here is what you see:
Now use Search > Bookmark > Remove Unmarked Lines and you get this:
The following RegEx maches the 2 lines with brackets containing 4 numbers:
.*?\(\d{4}\)\s*
It starts matching anything at start zero or more times (non greedy), then it matches a start bracket followed by 4 numbers. Finally ending White Space and new line.
If you want to remove all lines but the ones that end with (4numbers) you may try with this:
^(?!.*\(\d{4}\)\h*$).*(?:\r?\n|\z)
Replace by: (nothing)
See demo

Regex Match Paragraph Pattern

I am trying to match a paragraph pattern and I am having trouble.
The pattern is:
[image.gif]
some words, usually a few lines
name
emailaddress<mailto:theemailaddress#mail.com>
I tried matching everything between the gif image and the <mailto: but this happens multiple times in the file meaning I get a bad result.
I tried it with this
(?<=\[image.gif\].*?(\[image.gif\])).*?(?=<mailto:)
Is there a way to use Regex to match the general layout of a paragraph?
"the general layout of a paragraph" needs a better definition. Given the lack of an input plus expected output, I'm having to guess what you want here. I'm also guessing that you will accept any language. Here's perl, almost certainly not a language you're familiar with.
Assumed input:
do not match this line
[image.gif]
some words, usually a few lines
Bobert McBobson
emailaddress<mailto:bobertmb#example.com>
don't match this line either
[image.gif]
another few words
on another few lines
Bobina Robertsdaughter
emailaddress<mailto:bobinard#example.info>
this line is also not for matching
Expected output:
[image.gif]
some words, usually a few lines
Bobert McBobson
emailaddress<mailto:bobertmb#example.com>
---
[image.gif]
another few words
on another few lines
Bobina Robertsdaughter
emailaddress<mailto:bobinard#example.info>
Solution using perl:
#!/usr/bin/perl -n007
my $sep = "";
while (/(\[image\.gif\].*?<mailto:[^>]*>(\r)?\n)/gms) {
print $sep . $1;
$sep = "---$2\n";
}
perl is the king of regex languages; many would say that's all it is good for. Here, we use the -n007 option to tell it to read the entire contents of each file and run the code on it as the default variable.
$sep starts blank because there's nothing to separate until the second match.
Then we loop over each block of text that matches the regex:
matches a literal [image.gif]
then matches as little content following that as possible
then matches a literal <mailto: and continues until the next >
then captures the line break (including optional support for DOS line endings)
(see full regex explanation and example at regex101)
We then print the match and finally set the separator to three dashes and a line break (DOS line endings added when needed).
Now you can run it:
$ perl answer.pl input.txt
[image.gif]
some words, usually a few lines
Bobert McBobson
emailaddress<mailto:bobertmb#example.com>
---
[image.gif]
another few words
on another few lines
Bobina Robertsdaughter
emailaddress<mailto:bobinard#example.info>

How do you "quantify" a variable number of lines using a regexp?

Say you know the starting and ending lines of some section of text, but the chars in some lines and the number of lines between the starting and ending lines are variable, รก la:
aaa
bbbb
cc
...
...
...
xx
yyy
Z
What quantifier do you use, something like:
aaa\nbbbb\ncc\n(.*\n)+xx\nyyy\nZ\n
to parse those sections of text as a group?
You can use the s flag to match multilines texts, you can do it like:
~\w+ ~s.
There is a similar question here:
Javascript regex multiline flag doesn't work
If I understood correctly, you know that your text begins with aaa\nbbbb\ncc and ends with xx\nyyy\nZ\n. You could use aaa.+?bbbb.+?cc(.+?)xx.+?yyy.+?Z so that all operators are not greedy and you don't accidentally capture two groups at once. The text inbetween these groups would be in match group 1. You also need to turn the setting that causes dot to match new line on.
Try this:
aaa( |\n)bbbb( |\n)cc( |\n)( |\n){0,1}(.|\n)*xx( |\n)yyy( |\n)Z
( |\n) matches a space or a newline (so your starting and ending phrases can be split into different lines)
RegExr
At the end of the day what worked for me using Kate was:
( )+aaa\n( )+bbbb\n( )+cc\n(.|\n)*( )+xx\n( )+yyy\n( )+Z\n
using such regexps you can clear pages of quite a bit of junk.

I need a regex to repair lines split at column 80

Problem - Multiline, Semi-colon delimited file has been split at column 79 or 80 (not always the same for some strange reason).
It seems to me that a Regex would be the appropriate solution, so now I have two problems.
Lines are:
1sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
.....|.....|.....|.....|.....|.....|[cr][lf]
2sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
.....|.....|.....|.....|.....|.....|[cr][lf]
3sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
.....|.....|.....|.....|.....|.....|[cr][lf]
4sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
.....|.....|.....|.....|.....|.....|[cr][lf]
... 10000 rows ...
Where the pipe is a non-space whitespace character (possibly a tab)
I need:
1sdf.............................mnopqr........xyz......................[cr][lf]
2sdf.............................mnopqr........xyz......................[cr][lf]
3sdf.............................mnopqr........xyz......................[cr][lf]
4sdf.............................mnopqr........xyz......................[cr][lf]
I managed to get the job done with
Pass 1:
Replace ^\s*\r\n with \rxxx\n
// Replace Blank lines with \rxxx\n leaving
1sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
[cr]xxx[lf]
2sdf.............................mno[cr][lf]
pqr........xyz......................[cr][lf]
Pass 2:
Replace \r\n with [empty]
//leaving:
1sdf.............................mnopqr........xyz......................[cr]
xxx[lf]
2sdf.............................mnopqr........xyz......................
Pass 3:
Replace \rxxx\n with \r\n
//leaving:
1sdf.............................mnopqr........xyz......................[cr][lf]
2sdf.............................mnopqr........xyz......................
And the rest of the cleanup is trivial.
Is there any way of doing this in a single step? The output is from a common financial application, and I'd rather be able to fix the files myself rather than try and get many multiple clients to adjust their output.
In Notepad++ (using regular expression mode) you can use this:
Find what: \r\n(\s*\r\n)?
Replace with: \1
Then run "Replace All" exactly once. However, make sure you update to Notepad++ 6! Otherwise matching \r\n with a regular expression won't work in Notepad++.
Assuming that ^\s*\r\n match the line you want to remove as you said above, I believe you could do it with replacing \r\n\s*\r\n|\r\n by \r\n
It's my first regex, so if it doesn't work, don't be to harsh :-)
Good luck