How to replace all characters in a string except first and last characters, using JavaScript - javascript

I need to write a solution in JavaScript to replace all the characters in a string with a *, except for the first and last characters. I'm not very familiar with RegEx but was trying to use the following to achieve the solution:
var regex = /\.(?=^)(?!=$)/;
const censored = w.replace(regex)
console.log(censored)
Any ideas on how I can achieve this?

The idea of using lookaheads is viable, let's correct a few mistakes:
var regex = /(?<!^).(?!$)/g;
var w = 'fork'
var censored = w.replace(regex, '*')
console.log(censored)
Do note, however, that lookbehinds (?<= and ?<!) are from ES 2018 and not universally supported yet. (As pointed out in another answer, you actually don't need a lookbehind here, a lookahead (?!^) would do as well). Stil...
You can also chop off the first char and replace the rest:
var w = 'fork'
var censored = w[0] + w.slice(1).replace(/.(?!$)/g, '*')
console.log(censored)
Finally, here's a way to do that without any regexes at all:
var w = 'fork'
var censored = w[0] + '*'.repeat(w.length - 2) + w.slice(-1)
console.log(censored)

Here's a way without regex:
function censor(str) {
return str[0] + new Array(str.length - 2).join('*') + str[str.length - 1]
}
console.log(censor('happy birthday'))

It is very easy with an ECMAScript 5 compliant regex pattern:
var regex = /(?!^)[\s\S](?!$)/g;
var w = "Text!"
var censored = w.replace(regex, "*")
console.log(censored)
Details
(?!^) - negative lookahead: matches a location that is not a string start position
[\s\S] - any char (even a newline)
(?!$) - negative lookahead: matches a location that is not a string end position
See the regex demo.

You could use a replace callback as the second parameter to replace the items like this:
const str = 'fork'
var result = str.replace(/^(.)(.+)(.)$/, (whole, first, middle, last) => {
return first + new Array(middle.length).fill('*').join('') + last
})
console.log(result)

Here's a solution if regex is not a requirement.
function censor(input){
return input.split("").map(function(char, index){
if(index === 0 || index === (input.length - 1)){
return char;
} else {
return "*";
}
}).join("");
}
console.log(censor("Hello world"));

You can also use the following code:
(?<=\w{1})\w(?=\w{1})
where ?<= is positive lookbehind, and ?= is a positive lookahead

Related

Replace after char '-' or '/' match

I'm trying to execute regex replace after match char, example 3674802/3 or 637884-ORG
The id can become one of them, in that case, how can I use regex replace to match to remove after the match?
Input var id = 3674802/3 or 637884-ORG;
Expected Output 3674802 or 637884
You could use sbustring method to take part of string only till '/' OR '-':
var input = "3674802/3";
var output = input.substr(0, input.indexOf('/'));
var input = "637884-ORG";
var output = input.substr(0, input.indexOf('-'));
var input = "3674802/3";
if (input.indexOf('/') > -1)
{
input = input.substr(0, input.indexOf('/'));
}
console.log(input);
var input = "637884-ORG";
if (input.indexOf('-') > -1)
{
input = input.substr(0, input.indexOf('-'));
}
console.log(input);
You can use a regex with a lookahead assertion
/(\d+)(?=[/-])/g
var id = "3674802/3"
console.log((id.match(/(\d+)(?=[/-])/g) || []).pop())
id = "637884-ORG"
console.log((id.match(/(\d+)(?=[/-])/g) || []).pop())
You don't need Regex for this. Regex is far more powerful than what you need.
You get away with the String's substring and indexOf methods.
indexOf takes in a character/substring and returns an integer. The integer represents what character position the character/substring starts at.
substring takes in a starting position and ending position, and returns the new string from the start to the end.
If are having trouble getting these to work; then, feel free to ask for more clarification.
You can use the following script:
var str = '3674802/3 or 637884-ORG';
var id = str.replace(/(\d+)[-\/](?:\d+|[A-Z]+)/g, '$1');
Details concerning the regex:
(\d+) - A seuence of digits, the 1st capturing group.
[-\/] - Either a minus or a slash. Because / are regex delimiters,
it must be escaped with a backslash.
(?: - Start of a non-capturing group, a "container" for alternatives.
\d+ - First alternative - a sequence of digits.
| - Alternative separator.
[A-Z]+ - Second alternative - a sequence of letters.
) - End of the non-capturing group.
g - global option.
The expression to replace with: $1 - replace the whole finding with
the first capturing group.
Thanks To everyone who responded to my question, was really helpful to resolve my issue.
Here is My answer that I built:
var str = ['8484683*ORG','7488575/2','647658-ORG'];
for(i=0;i<str.length;i++){
var regRep = /((\/\/[^\/]+)?\/.*)|(\-.*)|(\*.*)/;
var txt = str[i].replace(regRep,"");
console.log(txt);
}

Remove Any Non-Digit And Check if Formatted as Valid Number

I'm trying to figure out a regex pattern that allows a string but removes anything that is not a digit, a ., or a leading -.
I am looking for the simplest way of removing any non "number" variables from a string. This solution doesn't have to be regex.
This means that it should turn
1.203.00 -> 1.20300
-1.203.00 -> -1.20300
-1.-1 -> -1.1
.1 -> .1
3.h3 -> 3.3
4h.34 -> 4.34
44 -> 44
4h -> 4
The rule would be that the first period is a decimal point, and every following one should be removed. There should only be one minus sign in the string and it should be at the front.
I was thinking there should be a regex for it, but I just can't wrap my head around it. Most regex solutions I have figured out allow the second decimal point to remain in place.
You can use this replace approach:
In the first replace we are removing all non-digit and non-DOT characters. Only exception is first hyphen that we negative using a lookahead.
In the second replace with a callback we are removing all the DOT after first DOT.
Code & Demo:
var nums = ['..1', '1..1', '1.203.00', '-1.203.00', '-1.-1', '.1', '3.h3',
'4h.34', '4.34', '44', '4h'
]
document.writeln("<pre>")
for (i = 0; i < nums.length; i++)
document.writeln(nums[i] + " => " + nums[i].replace(/(?!^-)[^\d.]+/g, "").
replace(/^(-?\d*\.\d*)([\d.]+)$/,
function($0, $1, $2) {
return $1 + $2.replace(/[.]+/g, '');
}))
document.writeln("</pre>")
A non-regex solution, implementing a trivial single-pass parser.
Uses ES5 Array features because I like them, but will work just as well with a for-loop.
function generousParse(input) {
var sign = false, point = false;
return input.split('').filter(function(char) {
if (char.match(/[0-9]/)) {
return sign = true;
}
else if (!sign && char === '-') {
return sign = true;
}
else if (!point && char === '.') {
return point = sign = true;
}
else {
return false;
}
}).join('');
}
var inputs = ['1.203.00', '-1.203.00', '-1.-1', '.1', '3.h3', '4h.34', '4.34', '4h.-34', '44', '4h', '.-1', '1..1'];
console.log(inputs.map(generousParse));
Yes, it's longer than multiple regex replaces, but it's much easier to understand and see that it's correct.
I can do it with a regex search-and-replace. num is the string passed in.
num.replace(/[^\d\-\.]/g, '').replace(/(.)-/g, '$1').replace(/\.(\d*\.)*/, function(s) {
return '.' + s.replace(/\./g, '');
});
OK weak attempt but seems fine..
var r = /^-?\.?\d+\.?|(?=[a-z]).*|\d+/g,
str = "1.203.00\n-1.203.00\n-1.-1\n.1\n3.h3\n4h.34\n44\n4h"
sar = str.split("\n").map(s=> s.match(r).join("").replace(/[a-z]/,""));
console.log(sar);

Javascript Remove strings in beginning and end

base on the following string
...here..
..there...
.their.here.
How can i remove the . on the beginning and end of string like the trim that removes all spaces, using javascript
the output should be
here
there
their.here
These are the reasons why the RegEx for this task is /(^\.+|\.+$)/mg:
Inside /()/ is where you write the pattern of the substring you want to find in the string:
/(ol)/ This will find the substring ol in the string.
var x = "colt".replace(/(ol)/, 'a'); will give you x == "cat";
The ^\.+|\.+$ in /()/ is separated into 2 parts by the symbol | [means or]
^\.+ and \.+$
^\.+ means to find as many . as possible at the start.
^ means at the start; \ is to escape the character; adding + behind a character means to match any string containing one or more that character
\.+$ means to find as many . as possible at the end.
$ means at the end.
The m behind /()/ is used to specify that if the string has newline or carriage return characters, the ^ and $ operators will now match against a newline boundary, instead of a string boundary.
The g behind /()/ is used to perform a global match: so it find all matches rather than stopping after the first match.
To learn more about RegEx you can check out this guide.
Try to use the following regex
var text = '...here..\n..there...\n.their.here.';
var replaced = text.replace(/(^\.+|\.+$)/mg, '');
Here is working Demo
Use Regex /(^\.+|\.+$)/mg
^ represent at start
\.+ one or many full stops
$ represents at end
so:
var text = '...here..\n..there...\n.their.here.';
alert(text.replace(/(^\.+|\.+$)/mg, ''));
Here is an non regular expression answer which utilizes String.prototype
String.prototype.strim = function(needle){
var first_pos = 0;
var last_pos = this.length-1;
//find first non needle char position
for(var i = 0; i<this.length;i++){
if(this.charAt(i) !== needle){
first_pos = (i == 0? 0:i);
break;
}
}
//find last non needle char position
for(var i = this.length-1; i>0;i--){
if(this.charAt(i) !== needle){
last_pos = (i == this.length? this.length:i+1);
break;
}
}
return this.substring(first_pos,last_pos);
}
alert("...here..".strim('.'));
alert("..there...".strim('.'))
alert(".their.here.".strim('.'))
alert("hereagain..".strim('.'))
and see it working here : http://jsfiddle.net/cettox/VQPbp/
Slightly more code-golfy, if not readable, non-regexp prototype extension:
String.prototype.strim = function(needle) {
var out = this;
while (0 === out.indexOf(needle))
out = out.substr(needle.length);
while (out.length === out.lastIndexOf(needle) + needle.length)
out = out.slice(0,out.length-needle.length);
return out;
}
var spam = "this is a string that ends with thisthis";
alert("#" + spam.strim("this") + "#");
Fiddle-ige
Use RegEx with javaScript Replace
var res = s.replace(/(^\.+|\.+$)/mg, '');
We can use replace() method to remove the unwanted string in a string
Example:
var str = '<pre>I'm big fan of Stackoverflow</pre>'
str.replace(/<pre>/g, '').replace(/<\/pre>/g, '')
console.log(str)
output:
Check rules on RULES blotter

Why is my RegExp ignoring start and end of strings?

I made this helper function to find single words, that are not part of bigger expressions
it works fine on any word that is NOT first or last in a sentence, why is that?
is there a way to add "" to regexp?
String.prototype.findWord = function(word) {
var startsWith = /[\[\]\.,-\/#!$%\^&\*;:{}=\-_~()\s]/ ;
var endsWith = /[^A-Za-z0-9]/ ;
var wordIndex = this.indexOf(word);
if (startsWith.test(this.charAt(wordIndex - 1)) &&
endsWith.test(this.charAt(wordIndex + word.length))) {
return wordIndex;
}
else {return -1;}
}
Also, any improvement suggestions for the function itself are welcome!
UPDATE: example: I want to find the word able in a string, I waht it to work in cases like [able] able, #able1 etc.. but not in cases that it is part of another word like disable, enable etc
A different version:
String.prototype.findWord = function(word) {
return this.search(new RegExp("\\b"+word+"\\b"));
}
Your if will only evaluate to true if endsWith matches after the word. But the last word of a sentence ends with a full stop, which won't match your alphanumeric expression.
Did you try word boundary -- \b?
There is also \w which match one word character ([a-zA-Z_]) -- this could help you too (depends on your word definition).
See RegExp docs for more details.
If you want your endsWith regexp also matches the empty string, you just need to append |^$ to it:
var endsWith = /[^A-Za-z0-9]|^$/ ;
Anyway, you can easily check if it is the beginning of the text with if (wordIndex == 0), and if it is the end with if (wordIndex + word.length == this.length).
It is also possible to eliminate this issue by operating on a copy of the input string, surrounded with non-alphanumerical characters. For example:
var s = "#" + this + "#";
var wordIndex = this.indexOf(word) - 1;
But I'm afraid there is another problems with your function:
it would never match "able" in a string like "disable able enable" since the call to indexOf would return 3, then startsWith.test(wordIndex) would return false and the function would exit with -1 without searching further.
So you could try:
String.prototype.findWord = function (word) {
var startsWith = "[\\[\\]\\.,-\\/#!$%\\^&\*;:{}=\\-_~()\\s]";
var endsWith = "[^A-Za-z0-9]";
var wordIndex = ("#"+this+"#").search(new RegExp(startsWith + word + endsWith)) - 1;
if (wordIndex == -1) { return -1; }
return wordIndex;
}

Javascript regular expression: remove first and last slash

I have these strings in javascript:
/banking/bonifici/italia
/banking/bonifici/italia/
and I would like to remove the first and last slash if it's exists.
I tried ^\/(.+)\/?$ but it doesn't work.
Reading some post in stackoverflow I found that php has trim function and I could use his javascript translation (http://phpjs.org/functions/trim:566) but I would prefer a "simple" regular expression.
return theString.replace(/^\/|\/$/g, '');
"Replace all (/.../g) leading slash (^\/) or (|) trailing slash (\/$) with an empty string."
There's no real reason to use a regex here, string functions will work fine:
var string = "/banking/bonifici/italia/";
if (string.charAt(0) == "/") string = string.substr(1);
if (string.charAt(string.length - 1) == "/") string = string.substr(0, string.length - 1);
// string => "banking/bonifici/italia"
See this in action on jsFiddle.
References:
String.substr
String.charAt
In case if using RegExp is not an option, or you have to handle corner cases while working with URLs (such as double/triple slashes or empty lines without complex replacements), or utilizing additional processing, here's a less obvious, but more functional-style solution:
const urls = [
'//some/link///to/the/resource/',
'/root',
'/something/else',
];
const trimmedUrls = urls.map(url => url.split('/').filter(x => x).join('/'));
console.log(trimmedUrls);
In this snippet filter() function can implement more complex logic than just filtering empty strings (which is default behavior).
Word of warning - this is not as fast as other snippets here.
One liner, no regex, handles multiple occurences
const trimSlashes = str => str.split('/').filter(v => v !== '').join('/');
console.log(trimSlashes('/some/path/foo/bar///')); // "some/path/foo/bar"
Just in case that someone needs a premature optimization here...
http://jsperf.com/remove-leading-and-trailing-slashes/5
var path = '///foo/is/not/equal/to/bar///'
var count = path.length - 1
var index = 0
while (path.charCodeAt(index) === 47 && ++index);
while (path.charCodeAt(count) === 47 && --count);
path = path.slice(index, count + 1)
you can check with str.startsWith and str.endsWith
then substr if exist
var str= "/aaa/bbb/";
var str= str.startsWith('/') ? str.substr(1) : str;
var str= str.endsWith('/') ? str.substr(0,str.length - 1) : str;
or you can write custom function
trimSlashes('/aaa/bbb/');
function trimSlashes(str){
str= str.startsWith('/') ? str.substr(1) : str;
str= str.endsWith('/') ? str.substr(0,str.length - 1) : str;
return str;
}

Categories

Resources