In Java, I want to write a regular expression to do the following:
source string: abcdefg
output string: ab***fg
source string: 123456789
output string: 12*****89
source string: a123d
output string: a1*3d
4 Answers
(?<!^.?).(?!.?$)
The idea is:
(?<!)- a negative lookbehind to ensure that^.?- the start of the string is not zero or one characters away.- the character that is going to be replaced(?!)- a negative lookahead to ensure that.?$- the end of the string is not zero or one characters away
Replace with single *.
2 Comments
Giuseppe Ricupero
cool, i leaved this path cause lookbehind does not accept variable size on pcre (default on regex101). One point for java regex engine
ndnenkov
@GiuseppeRicupero, yep, in java you can have lookbehinds with variable length as long as they are bound by finite length. :)
You can use
Find: (?<=..).(?=..)
Replace: *
Details:
(?<=..)- a positive lookbehind that requires any two chars other than line break chars immediately to the leftht of the current location.- any char other than a line break char(?=..)- a positive lookahead that requires any two chars other than line break chars immediately to the right of the current location.
See the regex demo.
Here are solutions for some languages:
- java -
text.replaceAll("(?<=..).(?=..)", "*") - javascript -
text.replace(/(?<=..).(?=..)/g, "*") - python -
re.sub(r"(?<=..).(?=..)", "*", text) - c# -
Regex.Replace(text, @"(?<=..).(?=..)", "*") - vb.net -
Regex.Replace(text, "(?<=..).(?=..)", "*") - ruby -
text.gsub(/(?<=..).(?=..)/, "*") - r -
gsub("(?<=..).(?=..)", "*", text, perl=TRUE) - php -
preg_replace('~(?<=..).(?=..)~', '*', $text) - perl -
$text =~ s/(?<=..).(?=..)/*/g; - postgresql -
REGEXP_REPLACE(text, '(?<=..).(?=..)', '*','g')
Comments
The following code use the regex (.{2})(.*)(.{2}) to do exactly what you asks (works with string from 5 chars above):
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String input = "1234567890";
final Pattern hidePattern = Pattern.compile("(.{1,2})(.*)(.{1,2})");
Matcher m = hidePattern.matcher(input);
String output;
if(m.find()) {
l = m.group(2).length();
output = m.group(1) + new String(new char[l]).replace("\0", "*") + m.group(3);
}
System.out.println(output); // 12******90
If you need to allow less then 5 chars (till 3 below does not make sense) use:
(.{1,2})(.+)(.{1,2})
Comments
\A.{2}(.+).{2}\z will return you what you want. Will not work if less than 5 characters. This is language dependent. My regex is in ruby. In ruby:
\A => start of string \z => end of string
find your language equivalents.
*in the middle need to reflect the substitution length?