Specific search pattern using regex - regex

I would like to search for a pattern in following type of strings.
I have both of these patterns
"<deliveries!ntg5!intel!api!ntg5!avt!tuner!src>CDAVTTunerTVProxy.cpp"
and
"<.>api/sys/mocca/pf/comm/component/src\HBServices.hpp"
I would like to extract the file names from the patterns above
I tried the following
if(m/(\|>[0-9a-zA-Z_]\.cpp"$|\.hpp"$|\.h"$|\.c")$/){
Above expression is not listing file names with " >xxxxx.cpp" ( or .hpp, or .h, or .c)
Any idea would be of great help.

There are a few mistakes in your regex
if(m/(\|>[0-9a-zA-Z_]\.cpp"$|\.hpp"$|\.h"$|\.c")$/){
I assume that \|> is supposed to match either \ or >, but this is incorrect. It will try to match a pipe | followed by >. Backslash is used to escape characters, and so if you want to match a literal backslash, you need to escape it: \\. This is the wrong way to use an alternation, though (see more below), and there is a better way, which is to use a character class: [\\>].
[0-9a-zA-Z_] is a character class that is represented by \w, so it makes sense to use that instead to make your regex more readable. Also, you are only matching one character. If you want to match more than that, you need to supply a quantifier, such as +, which is suitable in this case. The quantifier + means to match 1 or more times.
Your alternations | are mixed up. Unless you group them properly, they will be intended to match the entire string. Your regex as it is now would capture strings like:
|>A.cpp"
.hpp"
.c"
Which is not what you want. If you want to apply the different extensions to the main file name body, you have to group the alternate extensions properly:
\w+\.(?:cpp|hpp|h|c)"$
Using parentheses that do not capture (?: ... ) are suitable for grouping. As you can also see, there is no need to repeat the parts of the string which are identical for all extensions.
So what do we end up with?
/([\\>]\w+\.(?:cpp|hpp|h|c)")$/
Although I do not think that you really want to include the leading [\\>] in the match, or the trailing ". So more properly it would be
/[\\>](\w+\.(?:cpp|hpp|h|c))"$/
Note that as I said in the comment, there is a module to use if these are paths, and you want to extract the file name. File::Basename is included in Perl core since version 5.

Please try this regex:
m/([0-9a-zA-Z_]+\.(?:cpp|hpp|h|c))$/
This one is looking for the extension cpp, hpp, h or c at the end of the string(using $) and then looking for the file name just before the period(.) with extension.

Related

Regex to match word that contains exact word

I'm trying to filter specific files in Java by their names using Regex.
Idea being a lot of files are called SomethingSupport.java, AnotherSupport.java, MoreThingsSupport.java, so as they all have the "Support.java" I was trying to do:
[Support.java]
But of course that's meant for characters so it will filter S,u,p,o, etc... Looking through RegExr I've tried:
(Support.java)
But it takes all "Support.java" occurrences but I'm trying to take ThingsSupport.java, SomethingSupport.java, etc. not Support.java.
Parentheses just group things. There is no difference between what regex "Support.java" and regex "(Support.java)" would match.
Note that . is regexpese for any character, so, e.g. Supportxjava, unlikely as it is that you have a file with that name in your source base, would match too. \. is regexpese for "an actual dot, please".
I think you're looking for the regex .*Support.*\.java. Which means: Absolutely anything (0 or more any character), followed by the string Support, followed by absolutely anything again, followed by .java.
That would find e.g. FooSupportBar.java, Support.java, HelloSupport.java, and SupportHello.java. It wouldn't find anything that doesn't end in .java.

Extract specific string using regular expression

I want to extract only a specific string if its match
example as an input string:
13.10.0/
13.10.1/
13.10.2/
13.10.3/
13.10.4.2/
13.10.4.4/
13.10.4.5/
I'm using this regex [0-9]+.[0-9]+.[0-9] to extract only digit.digit.digit from a string if its match
but in that case, this is the wrong output related to my regex :
13.10.0
13.10.1
13.10.2
13.10.3
13.10.4.2 (no need to match this string 13.10.4 )
13.10.4.4 (no need to match this string13.10.4 )
13.10.4.5(no need to match this string 13.10.4 )
the correct output that I need :
13.10.0
13.10.1
13.10.2
13.10.3
It's hard to say without knowing how you're passing these strings in -- are they lines in a file? An array of strings in a programming language?
If you're searching a file using grep or a similar tool, it will give you all lines that match anywhere, even if only part of the line matches.
Normally, you'd deal with this using anchors to specify the regex must start on the first character of the line, and end on the last (e.g. ^[0-9]+.[0-9]+.[0-9]$). ^ matches the start of the line, and $ matches at the end.
In your case, you've got slashes at the end of all the lines, so the easiest fix is to match that final slash, with ^[0-9]+.[0-9]+.[0-9]/.
You could also use lookahead or groups to match the slash without returning it -- but that depends a bit more on what tool you're running this regex in and how you're processing it.
If your strings are separated by whitespace (other than newlines), replacing ^ with (^|\s) (either the beginning of the string, or some whitespace character) may work -- but it will add a leading space to some of your results.
You may also need to set your regex tool to match multiple times in a line (e.g. the -o flag in grep). Again, it's hard to give useful advice about this without knowing what regular-expression tool you're using, or how you're processing the results.
I think you want:
^\d+\.\d+\.\d+$
Which is exactly 3 groups of digit(s) separates by (literal) dots.
Some tools (like grep) match all lines that contain your regex, and may have additional characters before/after.
Use $ character to match end of line after your regex. (Also note, that . matches any character, not literal dot)
[0-9]+\.[0-9]+\.[0-9]$

Regex to find two words on the page

I'm trying to find all pages which contain words "text1" and "text2".
My regex:
text1(.|\n)*text2
it doesn't work..
If your IDE supports the s (single-line) flag (so the . character can match newlines), you can search for your items with:
(text1).*(text2)|\2.*\1
Example with s flag
If the IDE does not support the s flag, you will need to use [\s\S] in place of .:
(text1)[\s\S]*(text2)|\2[\s\S]*\1
Example with [\s\S]
Some languages use $1 and $2 in place of \1 and \2, so you may need to change that.
EDIT:
Alternately, if you want to simply match that a file contains both strings (but not actually select anything), you can utilize look-aheads:
(?s)^(?=.*?text1)(?=.*?text2)
This doesn't care about the order (or number) of the arguments, and for each additional text that you want to search for, you simply append another (?=.*?text_here). This approach is nice, since you can even include regex instead of just plain strings.
text0[\s\S]*text1
Try this.This should do it for you.
What this does is match all including multiline .similar to having .*? with s flag.
\s takes care of spaces,newlines,tabs
\S takes care any non space character.
If you want the regex to match over several lines I would try:
text1[\w\W]*text2
Using . is not a good choice, because it usually doesn't match over multiple lines. Also, for matching single characters I think using square brackets is more idiomatic than using ( ... | ... )
If you want the match to be order-independent then use this:
(?:text1[\w\W]*text2)|(?:text2[\w\W]*text1)
Adding a response for IntelliJ
Building on #OnlineCop's answer, to swap the order of two expressions in IntelliJ,you would style the search as in the accepted response, but since IntelliJ doesn't allow a one-line version, you have to put the replace statement in a separate field. Also, IntelliJ uses $ to identify expressions instead of \.
For example, I tend to put my nulls at the end of my comparisons, but some people prefer it otherwise. So, to keep things consistent at work, I used this regex pattern to swap the order of my comparisons:
Notice that IntelliJ shows in a tooltip what the result of the replacement will be.
For me works text1*{0,}(text2){0,}.
With {0,} you can decide to get your keyword zero or more times OR you set {1,x} to get your keyword 1 or x-times (how often you want).

Regular expression using negative lookbehind not working in Notepad++

I have a source file with literally hundreds of occurrences of strings flecha.jpg and flecha1.jpg, but I need to find occurrences of any other .jpg image (i.e. casa.jpg, moto.jpg, whatever)
I have tried using a regular expression with negative lookbehind, like this:
(?<!flecha|flecha1).jpg
but it doesn't work! Notepad++ simply says that it is an invalid regular expression.
I have tried the regex elsewhere and it works, here is an example so I guess it is a problem with NPP's handling of regexes or with the syntax of lookbehinds/lookaheads.
So how could I achieve the same regex result in NPP?
If useful, I am using Notepad++ version 6.3 Unicode
As an extra, if you are so kind, what would be the syntax to achieve the same thing but with optional numbers (in this case only '1') as a suffix of my string? (even if it doesn't work in NPP, just to know)...
I tried (?<!flecha[1]?).jpg but it doesn't work. It should work the same as the other regex, see here (RegExr)
Notepad++ seems to not have implemented variable-length look-behinds (this happens with some tools). A workaround is to use more than one fixed-length look-behind:
(?<!flecha)(?<!flecha1)\.jpg
As you can check, the matches are the same. But this works with npp.
Notice I escaped the ., since you are trying to match extensions, what you want is the literal .. The way you had, it was a wildcard - could be any character.
About the extra question, unfortunately, as we can't have variable-length look-behinds, it is not possible to have optional suffixes (numbers) without having multiple look-behinds.
Solving the problem of the variable-length-negative-lookbehind limitation in Notepad++
Given here are several strategies for working around this limitation in Notepad++ (or any regex engine with the same limitation)
Defining the problem
Notepad++ does not support the use of variable-length negative lookbehind assertions, and it would be nice to have some workarounds. Let's consider the example in the original question, but assume we want to avoid occurrences of files named flecha with any number of digits after flecha, and with any characters before flecha. In that case, a regex utilizing a variable-length negative lookbehind would look like (?<!flecha[0-9]*)\.jpg.
Strings we don't want to match in this example
flecha.jpg
flecha1.jpg
flecha00501275696.jpg
aflecha.jpg
img_flecha9.jpg
abcflecha556677.jpg
The Strategies
Inserting Temporary Markers
Begin by performing a find-and-replace on the instances that you want to avoid working with - in our case, instances of flecha[0-9]*\.jpg. Insert a special marker to form a pattern that doesn't appear anywhere else. For this example, we will insert an extra . before .jpg, assuming that ..jpg doesn't appear elsewhere. So we do:
Find: (flecha[0-9]*)(\.jpg)
Replace with: $1.$2
Now you can search your document for all the other .jpg filenames with a simple regex like \w+\.jpg or (?<!\.)\.jpg and do what you want with them. When you're done, do a final find-and-replace operation where you replace all instances of ..jpg with .jpg, to remove the temporary marker.
Using a negative lookahead assertion
A negative lookahead assertion can be used to make sure that you're not matching the undesired file names:
(?<!\S)(?!\S*flecha\d*\.jpg)\S+\.jpg
Breaking it down:
(?<!\S) ensures that your match begins at the start of a file name, and not in the middle, by asserting that your match is not preceded by a non-whitespace character.
(?!\S*flecha\d*\.jpg) ensures that whatever is matched does not contain the pattern we want to avoid
\S+\.jpg is what actually gets matched -- a string of non-whitespace characters followed by .jpg.
Using multiple fixed-length negative lookbehinds
This is a quick (but not-so-elegant) solution for situations where the pattern you don't want to match has a small number of possible lengths.
For example, if we know that flecha is only followed by up to three digits, our regex could be:
(?<!flecha)(?<!flecha[0-9])(?<!flecha[0-9][0-9])(?<!flecha[0-9][0-9][0-9])\.jpg
Are you aware that you're only matching (in the sense of consuming) the extension (.jpg)? I would think you wanted to match the whole filename, no? And that's much easier to do with a lookahead:
\b(?!flecha1?\b)\w+\.jpg
The first \b anchors the match to the beginning of the name (assuming it's really a filename we're looking at). Then (?!flecha1?\b) asserts that the name is not flecha or flecha1. Once that's done, the \w+ goes ahead and consumes the name. Then \.jpg grabs the extension to finish off the match.

concatenate multiple regexes into one regex

For a text file, I want to match to the string that starts with "BEAM" and "FILE PATH". I would have used
^BEAM.*$
^FILE PATH.*$
if I were to match them separately. But now I have to concatenate those two matching patterns into one pattern.
Any idea on how to do this?
A pipe/bar character generally represents "or" with regexps. You could try:
^(BEAM|FILE PATH).*$
The accepted answer is right but you may have redundancy in your Regular Expression.
^ means match the start of a line
(BEAM|FILE PATH) - means the string "BEAM" or the string "FILE PATH"
.* means anything at all
$ means match the end of the line
So in effect, all you are saying is match my strings at the beginning of the line since you don't care what's at the end. You could do this with:
^(BEAM|FILE PATH)
There are two cases where this reduction wouldn't be valid:
If you doing some with the matched string, so you want to match the whole line to pass the data to something else.
You're using a Regular Expression function that wants to match a whole string rather than part of it. You can sometimes solve this by picking the a different Regular Expression function or method. For example in Python use search instead of match.
If the above post doesn't work, try escaping the () and | in different ways until you find one that works. Some regex engines treat these characters differently (special vs. non-special characters), especially if you are running the match in a shell (shell will look for special characters too):
^\(BEAM|FILE PATH\).*$
%\(BEAM\|FILE PATH\).*$
etc.