简体   繁体   中英

How to get the inverse of a regular expression?

Let's say I have a regular expression that works correctly to find all of the URLs in a text file:

(http://)([a-zA-Z0-9\/\.])*

If what I want is not the URLs but the inverse - all other text except the URLs - is there an easy modification to make to get this?

You could simply search and replace everything that matches the regular expression with an empty string, eg in Perl s/(http:\\/\\/)([a-zA-Z0-9\\/\\.])*//g

This would give you everything in the original text, except those substrings that match the regular expression.

If for some reason you need a regex-only solution, try this:

((?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%]))|\A(?!http://[a-zA-Z0-9\/\.#?/%])).+?((?=http://[a-zA-Z0-9\/\.#?/%])|\Z)

I expanded the set of of URL characters a little ( [a-zA-Z0-9\\/\\.#?/%] ) to include a few important ones, but this is by no means meant to be exact or exhaustive.

The regex is a bit of a monster, so I'll try to break it down:

(?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%])

The first potion matches the end of a URL. http://[a-zA-Z0-9\\/\\.#?/%]+ matches the URL itself, while (?=[^a-zA-Z0-9\\/\\.#?/%]) asserts that the URL must be followed by a non-URL character so that we are sure we are at the end. A lookahead is used so that the non-URL character is sought but not captured. The whole thing is wrapped in a lookbehind (?<=...) to look for it as the boundary of the match, again without capturing that portion.

We also want to match a non-URL at the beginning of the file. \\A(?!http://[a-zA-Z0-9\\/\\.#?/%]) matches the beginning of the file ( \\A ), followed by a negative lookahead to make sure there's not a URL lurking at the start of the file. (This URL check is simpler than the first one because we only need the beginning of the URL, not the whole thing.)

Both of those checks are put in parenthesis and OR 'd together with the | character. After that, .+? matches the string we are trying to capture.

Then we come to ((?=http://[a-zA-Z0-9\\/\\.#?/%])|\\Z) . Here, we check for the beginning of a URL, once again with (?=http://[a-zA-Z0-9\\/\\.#?/%]) . The end of the file is also a pretty good sign that we've reached the end of our match, so we should look for that, too, using \\Z . Similarly to a first big group, we wrap it in parenthesis and OR the two possibilities together.

The | symbol requires the parenthesis because its precedence is very low, so you have to explicitly state the boundaries of the OR .

This regex relies heavily on zero-width assertions (the \\A and \\Z anchors, and the lookaround groups). You should always understand a regex before you use it for anything serious or permanent (otherwise you might catch a case of perl), so you might want to check out Start of String and End of String Anchors and Lookahead and Lookbehind Zero-Width Assertions .

Corrections welcome, of course!

如果我正确理解了这个问题,你可以使用搜索/替换...只是在表达式周围使用通配符,然后替换第一个和最后一个部分。

s/^(.*)(your regex here)(.*)$/$1$3/

im not sure if this will work exactly as you intend but it might help: Whatever you place in the brackets [] will be matched against. If you put ^ within the bracket, ie [^a-zA-Z0-9/.] it will match everything except what is in the brackets.

http://www.regular-expressions.info/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM