I have a file text like below:
java-environment-common (3-1)
jdk8-openjdk (8.u172-2)
libart-lgpl (2.3.21-4)
expect (5.45.4-1)
dejagnu (1.6.1-1)
cython2 (0.28.4-1)
python2-pytz (2018.5-1)
python2-sip (4.19.8-1)
And I want to remove all the text in bracket (bracket included).
I use %s/\(.*\)//g, but it remove each line.
Finally, I get the true answer: %s/\s\(.*\)//g! But why the result of the regex are so different, the second just remove a space.
Please tell me the reason, thanks!
You are accidentally creating capture groups by putting the escaping slash, \ before your brackets. To vim, this means that whatever you find thanks to the regex we place inside these brackets should be saved so we can use those values again in our replace. It's actually not searching for the brackets at all! What you are actually doing in %s/\s\(.*\)//g is finding a whitespace with \s followed by any number of any character, saving these characters for later use and then replacing everything found with nothing (not using the values you saved earlier). This also just so happens to delete your brackets and their contents but not for the reasons you think it is.
If you wanted to search for the brackets, delete them and delete everything inside them, the right way would be to not escape your brackets, like this:
:%s/\s(.*)$//g
here I am telling vim to find a whitespace, followed by an opening bracket, followed by any number of any characters, followed by a closing bracket, followed by a newline (endline) character, then I tell it to replace everything with nothing (indicated by// )
In the non-very magic mode, \(...\) creates a capturing group, you do not actually match literal ( and ) with \( and \).
You must be looking for
%s/\s*(.*)//g
After running this command, I get the following output:
java-environment-common
jdk8-openjdk
libart-lgpl
expect
dejagnu
cython2
python2-pytz
python2-sip
To only remove 0+ whitespaces and the following (...) substring at the end of the line you may use
%s/\s*([^()]*)$//g
Where
\s* - 0+ whitespaces
( - a literal ( (in a non-very magic mode)
[^()]* - 0+ chars other than ( and )
) - a literal ) (in a non-very magic mode)
$ - end of the line.
You can just use:
:%s/\s(.*)//g
Another command
:%norm f(D
% ...... the whole file
f( ..... jump to the next (
D ...... erases till the end of line
Using t( instead of f( we can also delete the spaces
You can also use :normal command (more info here : http://vim.wikia.com/wiki/Using_normal_command_in_a_script_for_searching)
in your specific case, you can use the following:
:normal /(/di
Explanation of the command: Look for a ( then di will delete inside the scope of the ().
Related
I am new to Regex world. I would like to rename the files that have time stamp added on the end of the file name. Basically remove last 25 characters before the extension.
Examples of file names to rename:
IMG523314(2021-12-05-14-51-25_UTC).jpg > IMG523314.jpg
Test run1(2021-08-05-11-32-18_UTC).txt > Test run1.txt
To remove 25 characters before the .extension (2021-12-05-14-51-25_UTC)
or if you like, remove the brackets ( ) which are always there and everything inside the brackets.
After the right bracket is always a dot '. "
Will Regex syntax as shown in the Tittle here, select the above? If yes, I wonder how it actually works?
Many Thanks,
Dan
Yes \(.*\) will select the paranthesis and anything inside of them.
Assuming when you ask how it works you mean why do the symbols work how they do, heres a breakdown:
\( & \): Paranthesis are special characters in regex, they signify groups, so in order to match them properly, you need to escape them with backslashes.
.: Periods are wildcard matcher, meaning they match any single character.
*: Asterisks are a quantifier, meaning match zero to inifite number of the previous matcher.
So to put everything together you have:
Match exactly one opening parathesis
Match an unlimited number of any character
Match exactly one closing bracket
Because of that closing bracket requirement, you put a limit to the infinite matching of the asterisk and therefore only grab the parenthesis and characters inside of them.
Yes, it's possible:
a='IMG523314(2021-12-05-14-51-25_UTC).jpg'
echo "${a/\(*\)/}"
and
b='Test run1(2021-08-05-11-32-18_UTC).txt'
echo "${b/\(*\)/}"
Explanation:
the first item is the variable
the second is the content to be replaced \(*\), that is, anything inside paranthesis
the third is the string we intend to replace the former with (it's empty string in this case)
I'm trying to catch a tag with a special syntax in a file with this regex :
([a-z0-9 >}\/])(\{(var)\:([a-z0-9\_\/\-\.]+)([\?0-9]+)*\})([a-z0-9 {<\/])
The tag looks like :
{var:contactText}
But as you can see in my regex, I want to catch what's before and after the {var:something}. My expression work fine except when the expression is alone in a line.
I've had m flag to prevent the problem but that's still not working.
Live example: https://regex101.com/r/6T6OJm/1/
Am I missing something? It seems to be the last part with ([a-z0-9 {<\/]) which doesn't accept line break, so what's the solution?
Like the cat, the "multiline" modifier is a false friend. The m modifier doesn't mean the pattern will run magically over multiple lines, It only changes the meaning of the ^ and $ anchors (from start/end of the string to start/end of the line).
All what you need is to figure potential white characters using the \s class (that includes also the carriage return \r and the newline \n characters).
~
([a-z0-9 >}/])
\s* ( { (var) : ([a-z0-9_/.-]+) ([?0-9]+)? } ) \s*
([a-z0-9 {</])
~xi
demo
Note that many characters in the pattern doesn't need to be escaped.
Since the pattern is a bit long, I used the x modifier to not take in account spaces in the pattern: it's more readable.
Not sure that all the capture groups are useful.
Im using Notepad++ Find and replace and I have regex that looks for [^|]\r which will find the end of the line that starts with 8778.
8778|44523|0||TENNESSEE|ADMINISTRATION||ROLL 169 BATCH 8|1947-09-22|0|OnBase
See Also 15990TT|
I want to basically merge that line with the one below it, so it becomes this:
8778|44523|0||TENNESSEE|ADMINISTRATION||ROLL 169 BATCH 8|1947-09-22|0|OnBase See Also 15990TT|
Ive tried the replace being a blank space, but its grabbing the last character on that line (an e in this case) and replacing that with a space, so its making it
8778|44523|0||TENNESSEE|ADMINISTRATION||ROLL 169 BATCH 8|1947-09-22|0|OnBas
See Also 15990TT|
Is there any way to make it essentially merge the two lines?
\r only matches a carriage return symbol, to match a line break, you need \R that matches any line break sequence.
To keep a part of a pattern after replacement, capture that part with parentheses, and then use a backreference to that group.
So you may use
([^|\r])\R
Replace with $1. Or with $1 if you need to append a space.
Details
([^|\r]) - Capturing group 1 ($1 is the backreference that refers to the group value from the replacement pattern): any char other than | and CR
\R - any line break char sequence, LF, CR or CRLF.
See the regex demo and the Notepad++ demo with settings:
The issue is you're using [^|] to match anything that's not a pipe character before the carriage return, which, on replacement, will remove that character (hence why you're losing an e).
If it's imperative that you match only carriage returns that follow non-pipe characters, capture the preceding character ([^|])\r$ and then put it back in the replacement using $1.
You're also missing a \n in your regex, which is why the replacement isn't concatenating the two lines. So your search should be ([^|])\r\n$ and your replace should be $1.
Find
(\r\n)+
For "Replace" - don't put anything in (not even a space)
I know that the character ^ finds a character at the start of a line, but I need to delete a left parentheses at the start of many lines. When I try to do a replace, I receive the following error:
Unmatched marking parenthesis ( or \(. The error occurred while parsing the regular expression: '^(>>>HERE>>>'.
What is the correct syntax when searching for the character ( at the start of a line?
You need to escape the parenthesis with a slash, \(
Textpad regex is pretty frustrating when you need to match parentheses, as both (-) and \(-\) make matching groups. (Very old versions of Textpad had only \(-\) as capturing markers, as unslashed parentheses were not "special".)
You can get around this by using a character class with one item, the relevant parenthesis. For example, when there's an error in java, a stack trace appears that looks in part like this:
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at day11$boardWrapper.toString(day11.java:85)
When running code through Textpad, you need a regex to catch the filename and line number. The pattern below captures those in \1 and \2, respectively, allowing me to configure the tool to let me jump directly to the offending line.
at.+[(]([^:]+):([0-9]+)[)]
at.+ offending function name
[(] (
( ) capturing group 1
[^:]+ anything not a colon (i.e., the filename)
: colon
( ) capturing group 2
[0-9]+ digits (line number)
[)] )
New to regex and I need to pattern match on some dates to change the format.
I'm going from mm/dd/yy to yyyy-mm-dd where there are no entries prior to 2000.
What I'm unfamiliar with is how to group things to use their respective references of \1, \2, etc.
Would I first want to match on mm/dd/yy with something like ( \d{2} ) ( \/\d{2} ) ( \/\d{2} ) or is it as easy as \d\d/\d\d/\d\d ?
Assuming my first grouping is partially the right idea, I'm looking to do something like:
:%s/old/new/g
:%s/ ( \d{2} ) ( \/\d{2} ) ( \/\d{2} ) / ( 20+\3) - (\3) - (\1) /g
EDIT: Sorry, the replace is going to a yyyy-mm-dd format with hyphens, not the slash.
I was going to comment on another answer but it got complicated.
Mind the magic setting. If you want unescaped parens to do grouping, you need to include \v somewhere in your pattern. (See :help magic).
You can avoid escaping the slashes if you use something other than slashes in the :s command.
You are close. :) You don't want all of those spaces though as they'll require spaces in the same places to match.
My solution, where I use \v so I don't need to escape the parens and exclamation points so I can use slashes in my pattern without escaping them:
:%s!\v(\d{2})/(\d{2})/(\d{2})!20\3-\2-\1!g
This will match "inside" items that start or end with three or more digits though, too. If you can give begin/end criteria then that'd possibly be helpful. Assuming that simple "word boundary" conditions work, you can use <>:
:%s!\v<(\d{2})/(\d{2})/(\d{2})>!20\3-\2-\1!g
To critique yours specifically (for learning!):
:%s/ ( \d{2} ) ( \/\d{2} ) ( \/\d{2} ) / ( 20+\3) - (\3) - (\1) /g
Get rid of the spaces since presumably you don't want them!
Your grouping needs either \( \) or \v to work
You also need \{2} unless you use \v
You are putting the slashes in groups two and three which means they'll show up in the replacement too
You don't want the parentheses in the output!
You're substituting text directly; you don't want the + after the 20 in the output
Try this:
:%s/\(\d\{2}\)\/\(\d\{2}\)\/\(\d\{2}\)/20\3-\2-\1/g
The bits you're interested in are: \(...\) - capture; \d - a digit; \{N} - N occurrences; and \/ - a literal forward slash.
So that's capturing two digits, skipping a slash, capturing two more, skipping another slash, and capturing two more, then replacing it with "20" + the third couplet + "-" + the second couplet + "-" + the first couplet. That should turn "dd/mm/yy" into "20yy-mm-dd".
ok, try this one:
:0,$s#\(\d\{1,2\}\)/\(\d\{1,2\}\)/\(\d\{1,2\}\)#20\3-\2-\1#g
I've removed a lot of the spaces, both in the matching section and the replacement section, and most of parens, because the format you were asking for didn't have it.
Some things of note:
With vi you can change the '/' to any other character, which helps when you're trying to match a string with slashes in it.. I usually use '#' but it doesn't have to be.
You've got to escape the parens, and the curly braces
I use the :0,$ instead of %s, but I think it has the same meaning -- apply the following command to every row between row 0 and the end.
For the match: (\d{2})\/(\d{2})\/(\d{2})
For the replace: 20\3\/\1\/\2