Related
I have an alphanumeric string, so I want to mask all the numbers in this string when the count of digits reaches 10. In this example, the digit count has reached the count of 10 two times irrespective of how many space, special character,s or digits are there
For ex:
string 1:- abc23 56 dfg %#34567fhgh0 1234567890 abc345
Output:- abc** ** dfg %#*****fhgh* ********** abc345
It ignores the characters and mask the number when the digit length reaches 10. I want to do this with regex. How can I do that?
You may use something like this:
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
}
This will count the number of digit matches. If there are 10 or more digits, it replaces each one with a '*' character. If you want to only replace the digits if the string contains at least one set of 10 consecutive digits, see the end of the answer.
Here's a complete example:
var arr = ['abc23 56 dfg %#34567fhgh0 1234567890 abc345', 'abc123def'];
for (var i = 0; i < arr.length; i++) {
let s = arr[i];
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
arr[i] = s;
}
console.log(s);
}
Output:
abc** ** dfg %#*****fhgh* ********** abc***
abc123def
If you want the condition to be for 10 consecutive digits, use the following instead:
if (/\d{10}/g.test(s)) {
s = s.replace(/\d/g, '*');
}
You could split() the string into an array, check the length of the string, if it is over 10, then map the mask character where the number was using splice and its key along with Number and isNan.
var str = 'abc23 56 dfg %#34567fhgh0 1234567890'
var str2 = 'abc345'
var str3 = '%#34567fhg7'
var str4 = '1234567890'
const exchange = (str, cap) => {
// split the string and define array
const arr = str.split('')
// condtional to see if string.length is greater than cap
if (str.length > cap) {
// we have a string longer than cap, loop over the array, exclude
// empty spaces and check if value is a number using isNaN, if it is,
// we splice its value using the key with the mask character x
arr.map((char, k) => char !== ' ' ? Number.isNaN(Number(char)) ? null : arr.splice(k, 1, 'x') : null)
// return the value as a string by joining the array values together
return arr.join('')
} else {
// return the string as its length is not more than cap
return str
}
}
console.log(`${exchange(str, 10)}, length = ${str.length}`)
console.log(`${exchange(str2, 10)}, length = ${str2.length}`)
console.log(`${exchange(str3, 10)}, length = ${str3.length}`)
console.log(`${exchange(str4, 10)}, length = ${str4.length}`)
I'm working with numbers like 0.3333333333333333, 0.1111111111111111, 0.6666666666666666 and I'd like to round them to the nearest hundredth while keeping numbers like 0.14285714285714285 intact.
Sorry if this question's been asked. It's gotta be a common question, but I can't seem to come up with the right keywords.
There may be a mathematical way to detect those, but you can detect those on the string version of the number using a regular expression like this: /^0\.(\d)\1+$/. That says
^0. Must start with 0.
(\d) Followed by a digit (we capture this digit)
\1+ Followed by the same digit (\1 refers back to the capture group) one or more times (+
Then grab just the first four characters of the string if you want to truncate (0.6666666666666666 becomes 0.66) or the first five and convert back to number and round (0.6666666666666666 becomes 0.67).
Live Example:
const numbers = [
0.3333333333333333,
0.1111111111111111,
0.6666666666666666,
0.14285714285714285,
0.1444444444444444,
];
for (const number of numbers) {
const str = String(number);
if (/^0\.(\d)\1+$/.test(str)) {
const truncated = Number(str.substring(0, 4));
const rounded = Math.round(Number(str.substring(0, 5) * 100)) / 100;
console.log(`Truncated: ${truncated}, rounded: ${rounded}`);
} else {
console.log(`Unchanged; ${number}`);
}
}
(Convert back to number if you need the number value.)
In modern environments, you can make that expression a bit clearer by using a named capture group rather than the traditional anonymous version above: /^0\.(?<digit>\d)\k<digit>+$/ In that, (?<digit>\d) is the capture group named "digit" and \d<digit> is a backreference to that capture group.
Live Example:
const numbers = [
0.3333333333333333,
0.1111111111111111,
0.6666666666666666,
0.14285714285714285,
0.1444444444444444
];
for (const number of numbers) {
const str = String(number);
if (/^0\.(?<digit>\d)\k<digit>+$/.test(str)) {
const truncated = Number(str.substring(0, 4));
const rounded = Math.round(Number(str.substring(0, 5) * 100)) / 100;
console.log(`Truncated: ${truncated}, rounded: ${rounded}`);
} else {
console.log(str);
}
}
There's question what you want done with 0.1444444444444444 (do you want 0.1444444444444444 or 0.14)? All your examples repeat starting at the ., but you're rounding to hundreths. Now, those are two separate things, but people are interpreting your question to say that 0.1444444444444444 should become 0.14. If so, it's a trivial change to allow any digit in the tens place: Just add \d after . in the expression: /^0\.\d(\d)\1+$/
Live Example:
const numbers = [
0.3333333333333333,
0.1111111111111111,
0.6666666666666666,
0.14285714285714285,
0.1444444444444444,
0.1555555555555555,
];
for (const number of numbers) {
const str = String(number);
if (/^0\.\d(\d)\1+$/.test(str)) {
const truncated = Number(str.substring(0, 4));
const rounded = Math.round(Number(str.substring(0, 5) * 100)) / 100;
console.log(`Truncated: ${truncated}, rounded: ${rounded}`);
} else {
console.log(str);
}
}
Since your question is not so clear, I took it as follows:
If there is a repeating chunk of digits, keep the pattern twice and
truncate the rest. If there is not repeating digits, rounding to hundreths.
For example, the following is what you get by running the proposed code. The suffix ... is to indicate the repeated digits.
0.14285714285714285 => 0.142857142857... (repeating pattern = 142857)
0.1444444444444444 => 0.144... (repeating pattern = 4)
0.3333333333333333 => 0.33... (repeating pattern = 3)
0.1428824114288241 => 0.1428824114288241... (repeating pattern = 14288241)
0.1288241128824112 => 0.12882411288241... (repeating pattern = 1288241)
0.12128824112882411 => 0.1212882411288241... (repeating pattern = 1288241)
0.1231231231231231 => 0.123123... (repeating pattern = 123)
0.101010101010101 => 0.1010... (repeating pattern = 10)
0.12300123123123123 => 0.12300123123... (repeating pattern = 123)
0.4254250042542542 => 0.42542500425425... (repeating pattern = 425)
0.1232435213443346 => 0.12 (repeating pattern = None)
I had to create the test case to make sure the code works for various patterns. The nums array contains the input and the expected answer.
You can use the code as
const {result, pattern} = testRepeatingDigits (0.1444444)
If you want to round the answer, you can modify the code where it returns the number string with ....
If you give me your requirement I can always edit and improve the answer.
Here is the complete code that you can run and see.
/**
* Returns the logest repeating substring from the beginning.
*/
function findLongestSubstring (str) {
let candidate = "";
for (let i = 1; i <= str.length - i; i++) {
if (str.indexOf(str.substring(0, i), i) === i)
candidate = str.substring(0, i);
}
return candidate;
}
/**
* Rotate the substring and find the left most matched point
*/
function rotateAndMoveLeft (str, substr, fromIndex) {
const rotate = (str) => `${str[str.length-1]}${str.slice(0, str.length-1)}`;
const lastIndex = substr.length - 1;
let rotatedStr = substr;
let pos;
// console.log(`str=${str}, substr=${substr}, fromIndex=${fromIndex}`);
for (pos = fromIndex - 1; pos >= 0; pos--) {
if (rotatedStr[lastIndex] === str[pos]) {
rotatedStr = rotate(rotatedStr);
} else {
pos++;
break;
}
}
const from = pos !== -1 ? pos : 0;
return {
subStr: rotatedStr,
from,
numMoved: fromIndex - from
};
}
function shrinkPattern (pattern) {
const _shrink = (head, tail) => {
if (tail.length === 0)
return head;
return tail.split(head).every(item => item.length === 0) ?
head : _shrink(`${head}${tail[0]}`, tail.slice(1));
}
return _shrink(pattern[0], pattern.slice(1));
}
function testRepeatingDigits (num) {
const str = num.toString();
const idx = str.indexOf('.');
if (idx < 0)
return false;
const digitStr = str.substring(idx + 1);
const [...digits] = digitStr;
// the first guess of repeating pattern from the right-most digit
const init = [...findLongestSubstring(digits.slice(0).reverse().join(''))].reverse().join('');
// no repeating patterns found
if (init.length === 0)
return {
result: (Math.round(num * 100) / 100).toString(),
pattern: "None"
};
// rotate the first guessed pattern to the left to find the beginning of the repeats
const searchFrom = digitStr.length - (init.length * 2);
const { subStr, from, numMoved } = searchFrom > 0 ?
rotateAndMoveLeft(digitStr, init, searchFrom) : { subStr: init, from: 0, numMoved: 0 };
// shrink the pattern to minimum
const pattern = shrinkPattern(subStr);
// truncate the digits overflows the two repeatings of the pattern
return {
result: `${str.substring(0, idx+1)}${digitStr.substring(0, from + pattern.length * 2)}...`,
pattern
};
}
// test cases
const nums = [{
num: 0.14285714285714285, // rep: 142857, truncated: [14285]
str: '0.142857142857...'
},
{
num: 0.1444444444444444, // rep: 4, truncated: [4444444444444]
str: '0.144...'
},
{
num: 0.3333333333333333, // rep: 3, truncated: [33333333333333]
str: '0.33...'
},
{
num: 0.1428824114288241, // rep: 14288241, truncated: []
str: '0.1428824114288241...'
},
{
num: 0.1288241128824112, // 1288241, [12]
str: '0.12882411288241...'
},
{
num: 0.12128824112882411, // 1288241, [1]
str: '0.1212882411288241...'
},
{
num: 0.1231231231231231, // 123, [1]
str: '0.123123...'
},
{
num: 0.1010101010101010, // 10, [101010101010]
str: '0.1010...'
},
{
num: 0.12300123123123123, // 123, [123123]
str: '0.12300123123...'
},
{
num: 0.4254250042542542, // 425, [42]
str: '0.42542500425425...'
},
{
num: 0.1232435213443346, // no repeat
str: '0.12'
},
];
nums.forEach(({ num, str }) => {
const { result, pattern } = testRepeatingDigits(num);
console.log(`${num} => ${result} (repeating pattern = ${pattern}) ${result === str ? 'OK' : 'Incorrect!'} `);
});
Not perfectly clear but here is my take.
It feels like you would like to test the floating part of given number against a repeating pattern. So perhaps you can do like;
function truncAtRepeat(n){
var [is,fs] = String(n).split("."),
index = (fs + fs).indexOf(fs,1);
return index === fs.length ? n
: parseFloat(is + "." + fs.slice(0,index));
}
console.log(truncAtRepeat(1.177177177177177));
console.log(truncAtRepeat(1.17717717717717));
console.log(truncAtRepeat(3.14159265359));
use a list and iterate over each number in the string and find the repeating numbers
def find_repeating_numbers(string):
# create a list of numbers
numbers = [int(x) for x in string]
# create a list of repeating numbers
repeating_numbers = []
# iterate through the list of numbers
for i in range(len(numbers)):
# if the number is already in the list of repeating numbers, continue
if numbers[i] in repeating_numbers:
continue
# if the number is not in the list of repeating numbers, check if it is repeated
else:
# if the number is repeated, add it to the list of repeating numbers
if numbers.count(numbers[i]) > 1:
repeating_numbers.append(numbers[i])
# return the list of repeating numbers
return repeating_numbers
data=[0.14285714285714285,0.1444444444444444,0.3333333333333333
,0.1428824114288241,0.1288241128824112,0.12128824112882411,0.1231231231231231
,0.101010101010101,0.12300123123123123,0.4254250042542542,0.1232435213443346
]
# print the list of repeating numbers
#print(find_repeating_numbers('14285714285714285'))
for item in data:
item=re.sub('0.','',str(item))
result=find_repeating_numbers(item)
repeating_number=''.join([str(n) for n in result])
print(item,repeating_number)
output:
14285714285714285 142857
1444444444444444 4
3333333333333333 3
1428824114288241 1428
1288241128824112 1284
12128824112882411 1284
1231231231231231 123
1
123123123123123 123
42542542542542 425
1232435213443346 1234
I am trying to create a function that would remove certain characters from a phone number field. So far I have removed parenthesis, spaces, and hyphens as in (321) 321-4321. Also, I removed dots as in 321.321.4321. Lastly, I have validated when 11 digits and starting with 1 even with punctuation.
The code I input:
function phoneNumber(){
var number = '(321) 321-4321';
number = number.replace(/[^\d]/g, '');
return number;
}
I am now trying to have it return null for certain situations like:
When the number exceeds 11 digits
When letters and/or punctuation are present
When the area code does not start with 2-9
When the exchange code does not start with 2-9.
Any attempt to add a statement invalidates my original function. Can anyone help me I am new to regex, but I need help?
Brief
If I understand correctly, you want:
To remove any non-digit characters from the string
To get numbers that are 11 digits in length (or less)
To ensure the first and fourth digits in the number are in the range 2-9 (so not 0 or 1)
Code
The first regex can use \D instead of [^\d] as they both mean the exact same thing.
The second part can use any of the following methods (and more, but these are probably some of the simplest methods):
Regex and .length
/^[2-9]\d{2}[2-9]/.test(number) && number.length <= 11
var numbers = [
'(321) 321-4321',
'321.321.4321',
'123.456.7890',
'321.123.4567',
'(321) 321-4321-321'
];
function phoneNumber(number){
number = number.replace(/\D/g, '');
if(/^[2-9]\d{2}[2-9]/.test(number) && number.length <= 11) {
return number;
}
return null;
}
numbers.forEach(function(number){
console.log(phoneNumber(number));
});
charAt, regex and length
!/[01]/.test(number.charAt(0)) && !/[01]/.test(number.charAt(3)) && number.length <= 11
var numbers = [
'(321) 321-4321',
'321.321.4321',
'123.456.7890',
'321.123.4567',
'(321) 321-4321-321'
];
function phoneNumber(number){
number = number.replace(/\D/g, '');
if(!/[01]/.test(number.charAt(0)) && !/[01]/.test(number.charAt(3)) && number.length <= 11) {
return number;
}
return null;
}
numbers.forEach(function(number){
console.log(phoneNumber(number));
});
Regex (alone)
Obviously, you'd change 0 to whatever your minimum digits requirements are (minus 4); so if you want a minimum of 9, you'd put {5,7}.
/^[2-9]\d\d[2-9]\d{0,7}$/.test(number)
var numbers = [
'(321) 321-4321',
'321.321.4321',
'123.456.7890',
'321.123.4567',
'(321) 321-4321-321'
];
function phoneNumber(number){
number = number.replace(/\D/g, '');
if(/^[2-9]\d\d[2-9]\d{0,7}$/.test(number)) {
return number;
}
return null;
}
numbers.forEach(function(number){
console.log(phoneNumber(number));
});
Try as follows use .length to get characters in string
var number = '(321) 321-4321';
number = number.replace(/[^\d]/g, '');
console.log(number)
if (number.length > 11) {
console.log("null");
} else {
console.log(number.length);
}
if (number.match(/[a-z]/i)) {
console.log("alphabet letters found");
} else {
console.log("alphabet letters not found");
}
I have a Javascript array of strings that I'm sorting using the compareFunction. For the most part, it's sorting correctly:
JS
array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"];
function sortStrings(a, b){
if(a < b){
return -1;
}
if(a > b){
return 1;
}
return 0;
}
array.sort(sortStrings);
for(var i = 0; i < array.length; i++){
$(".table_body").append("<div class='table_row'><p>" +array[i] +"</p></div>");
}
The issue I'm having is the sort function is putting the "E10N10" item between"E10N1" and "E10N2" items. So it looks like this:
I understand that sorting strings is done alphabetically, but wouldn't the "E10N10" string still be processed as later than "E10N9"? How do I fix it to have this particular string come last in the array after it's sorted?
You can modify your custom sorting function to handle this. For example, if all of your strings start with 4 characters that you don't care about when sorting, just do this:
function sortStrings(a, b){
a = parseInt(a.substr(4));
b = parseInt(b.substr(4));
if(a < b){
return -1;
}
if(a > b){
return 1;
}
return 0;
}
In alphabetical sort, it just looks at the characters sequentially so "E10N1" would be before "E10N9", even though there is another character after the "E10N1". Just like "abcd" comes before "abd".
If you really want the type of sort you're asking for, it is going to take a much more complicated custom sort algorithm that actually parses the numeric parts of the tag to do actual numeric comparisons (not alphabetic sorts) on them.
Here's is a sorting scheme that sorts based on the trailing digits:
var array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"];
var regex = /\d+$/;
function getLastNum(str) {
var m = str.match(regex);
if (m) {
return parseInt(m[0], 10);
} else {
return -1;
}
}
array.sort(function(a, b) {
return getLastNum(a) - getLastNum(b);
});
document.write(JSON.stringify(array));
You can obviously make this as complicated or rich as desired. For example, if you want to identify all numeric sequences in the number and turn each of them into actual numbers, you can do that too. You did not specify how involved this needs to be so I showed the smallest work required to make your specific sequence work (by sorting just by the trailing digits).
For a discussion of several different general purpose algorithms for handling mixed alpha-numeric sorts where the digits can occur anywhere in the string and can occur in multiple places, you can see this article: Sorting for Humans: Natural Sort Order. One particular implementation in Javascript can be found here.
The general idea behind the generic algorithm is as follows:
Get the next character of each string
If not both digits, then compare the characters directly and return the result
If both digits, then collect sequence of digits in both strings
Longest sequence of consecutive digits is higher
While accumulating sequential digits, keep track of which sequence
has the first non-equal digit that is higher than the other
If sequences were the same length, then the previous collected value
of which sequence had the first different higher number determines
which sequence comes first
If sequence of digits or single character were equal, go to next character
and start the above process over
One advantage of this generic algorithm is that it does not actually convert the numeric sequences of digits to a number so it will work on sequences of numbers of arbitrary length without running into limitations on how many digits a number can be in Javascript.
Depending upon your desired algorithm, you may or may not want to ignore whitespace preceding digits and you may or may not want to account for plus or minus signs in front of numbers. And, you may want to use a language aware comparison rather than a strict ascii code comparison. There are lots of factors to consider for any particular use.
Here is a general purpose algorithm that I wrote from scratch:
var array = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5",
"E10N8", "E10N6", "E10N7", "C10N1", "D10N3", "E11N10", "E09N2", "E999N4",
"E10000N9", "g10N6", "z10N6", "q10N6", "R10N6", "E001N1", "E00N1",
"E0000N1", "zN1", "zN000", "zN00", "000", "00", "0001", "0002", "A00",
"A", "0A"];
// return negative value if a < b
// return 0 if a === b
// return positive value if a > b
//
// Rules:
// - Sort characters before numbers
// - Ignore leading zeroes on digits
// - Ignore plus/minus signs in front of digits
// - For sequences of zeroes the shorter sequence is first
//
function alphaNumCompare(a, b) {
var aIndex = 0,
bIndex = 0,
aChar, bChar, result;
function isDigit(ch) {
return ch >= "0" && ch <= "9";
}
function compareNums() {
// aChar, bChar contain first digit
// get rest of consecutive digits and compare
// returns negative, 0 or positive
// as side affect, advances aIndex and bIndex to next non-numeric
var aZeroLen = 0,
bZeroLen = 0,
aNumStr = "",
bNumStr = "";
// collect consecutive digits from a and b
// ignore any leading zeroes
if (aChar === "0") {
++aZeroLen;
} else {
aNumStr = aChar;
}
if (bChar === "0") {
++bZeroLen;
} else {
bNumStr = bChar;
}
while (aIndex < a.length) {
aChar = a.charAt(aIndex);
if (!isDigit(aChar)) {
break;
}
++aIndex;
// don't add leading zeroes and keep a count of leading zeroes
if (aChar === "0" && aNumStr === "") {
++aZeroLen;
} else {
aNumStr += aChar;
}
}
while (bIndex < b.length) {
bChar = b.charAt(bIndex);
if (!isDigit(bChar)) {
break;
}
++bIndex;
// don't add leading zeroes and keep a count of leading zeroes
if (bChar === "0" && bNumStr === "") {
++bZeroLen;
} else {
bNumStr += bChar;
}
}
// we now have a series of consecutive digits in aNumStr and bNumStr
if (aNumStr.length === bNumStr.length) {
// check for nothing but leading zeroes in both
if (aNumStr.length === 0) {
return aZeroLen - bZeroLen;
}
if (aNumStr === bNumStr) {
return 0;
} else {
return aNumStr < bNumStr ? -1 : 1;
}
} else {
// lengths are not equal, then shorter string comes first
return aNumStr.length - bNumStr.length;
}
}
// loop while both strings have characters left
while (aIndex < a.length && bIndex < b.length) {
aChar = a.charAt(aIndex++);
bChar = b.charAt(bIndex++);
if (isDigit(aChar) && isDigit(bChar)) {
result = compareNums();
if (result !== 0) {
return result;
}
} else {
// not both numeric, just compare the characters themselves
result = aChar.localeCompare(bChar);
if (result !== 0) {
return result;
}
}
}
// shorter one is first
return (a.length - aIndex) - (b.length - bIndex);
}
array.sort(alphaNumCompare);
document.write(JSON.stringify(array).replace(/,/g, ", "));
The logic for this is as follows:
Implement a custom sort function for the Array sort() function.
Get next character in the string
If both are digits, then accumulate whatever sequence of consecutive digits there are.
Trim leading zeroes from the sequence of zeroes
If both sequences are only a sequence of zeroes, then the shorter one is less
The shorter sequence of numbers is less than the longer one
If both sequences of numbers are the same length, then you can just do a straight string compare on them to get the result
If both characters are not digits, then just compare them as a string
If strings have compared equal up to the point where one ends, then the shorter one is less
I suggest to use a kind of sort pattern for this special purpopse.
var data = ["E10N1", "E10N3", "E10N10", "E10N2", "E10N4", "E10N9", "E10N5", "E10N8", "E10N6", "E10N7"],
result = data.map(function (el, i) {
var a = /(\D*)(\d*)(\D*)(\d*)/i.exec(el);
a.shift();
return { index: i, value: a };
}).sort(function (a, b) {
var i = 0, r = 0;
while (r === 0 && i < a.value.length && i < b.value.length) {
r = i % 2 ? +a.value[i] - +b.value[i] : a.value[i].localeCompare(b.value[i]);
i++;
}
return r;
}).map(function (el) {
return data[el.index];
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You could use a regex to capture the digits at the end of each element and sort on those instead:
function sortStrings(a, b) {
var regex = /E10N([\d]+)/;
var apost = +a.match(regex)[1];
var bpost = +b.match(regex)[1];
if (apost < bpost) return -1;
if (apost > bpost) return 1;
return 0;
}
DEMO
In ASCII order 1 is less than 9 so "E10N10" is less than "E10N9". To get result you want, you need sorts the numbers in value order, while sorting the non-numbers in ASCII order. You can use this Alphanum Algorithm:
http://www.davekoelle.com/alphanum.html
I need a regex which will test the combination of hexadecimal string. Specifically, the string must have:
Atleast one digit in the range 0 - 9,
At least one digit in the range A - F,
be 12 characters long.
String should not start with 0
Currently I am using var macRegex = new RegExp("^[0-9A-Fa-f]{12}$");. The above regex allow strings like "111111111111" , "000000000000" which i want to avoid . It should allow a string like "944a0c122123"
How can I accomplish this?
To keep the regular expression simple, I'd separate matching the pattern and checking the length:
var re = /^(\d+[a-f]+[\da-f]*|[a-f]+\d+[\da-f]*)$/i;
var s = '011001aFFA77';
console.log(re.test(s) && s.length == 12); // true
var s = '000000000000';
console.log(re.test(s) && s.length == 12); // false
The pattern to match:
one or more digits followed by one or more letters a to f followed by zero or more digits or letters a to f, OR
one or more letters a to f followed by one or more digits followed by zero or more digits or letters a to f
then check the length is 12.
Edit
To meet the new criterion "can't start with 0" (and simplify the expression a bit), the regular expression can be:
var re = /^([1-9]\d*[a-f]+|[a-f]+\d+)[\da-f]*$/i;
var s = '011001aFFA77';
console.log(re.test(s) && s.length == 12); // false
var s = '000000000000';
console.log(re.test(s) && s.length == 12); // false
var s = '011001aFFA77';
console.log(re.test(s) && s.length == 12); // false
var s = 'a11001aFFA77';
console.log(re.test(s) && s.length == 12); // true
var s = '311001aFFA77';
console.log(re.test(s) && s.length == 12); // true
var s = '0000000000a1';
console.log(re.test(s) && s.length == 12); // false
If you don't mind a non RegExp solution this function should do what you want.
function only_hex_len_12(str){
// if the string is the wrong length return false
if(str.length!=12) return false;
var hex_val=parseInt(str,16);
var dec_val=parseInt(str,10);
// If the string is dec return false
if(!isNaN(dec_val)) return false;
// If the string is not hex return false
if(isNaN(hex_val)) return false;
// Otherwise the string is okay so return true
return true;
}
If you want a RegExp solution RobG's answer looks good.
Here is the way I'd go:
/^(?=.*\d)(?=.*[a-f])[1-9a-f][\da-f]{10}[1-9a-f]$/i
Explanation:
/
^ : begining of string
(?=.*\d) : lookahead, at least one digit
(?=.*[a-f]) : lookahead, at least one letter in range a-f
[1-9a-f] : first character, not zero
[\da-f]{10} : ten hex character
[1-9a-f] : last character, not zero
$ : end of string
/i : case insensitive
You can use a set of positive lookaheads to do this.
Here's the regex:
/(?!0).(?=.*\d)(?=.*[a-f])[\da-f]{11}/i
(?!0) Negative lookahead
. Match any character
(?= Positive lookahead
.* Match any character zero to unlimited
\d Match a digit
)
(?= Positive lookahead
.* Match any character zero to unlimited
[a-f] Match a character a-f
)
[\da-f]{11} Match any of the valid characters, 12 times
You can conceptualize this is a logical AND of the expressions in each lookahead (except for the .*).
var regexp = /(?!0).(?=.*\d)(?=.*[a-f])[\da-f]{11}/i;
var test1 = "000000000000";
var test2 = "111111111111";
var test3 = "8179acf0871a";
var test4 = "9abzzzzzzzzz";
var test5 = "0179acf0871a";
console.log(regexp.test(test1));
console.log(regexp.test(test2));
console.log(regexp.test(test3));
console.log(regexp.test(test4));
console.log(regexp.test(test5));
Here's a snippet that demonstrates similar input samples.