Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript Regex restrict underscore at start and end

I have a form where I want to restrict first and last characters. (javascript) Restriction is:

  • Input must start and end with alphanumeric, not underscore while just underscore is allowed in between alphanumeric.

Examples:

 Valid Entries: abc, ABC, Abc123, 123a, Abc_12, Abc_12_3a
 Invalid Entries: _abc, abc_, _abc_

I tried to create my regex as below:

^(?!\_)(?!_*_$)[a-zA-Z0-9_]+$

This does not allow underscore at the start which is fine but does allows underscore at the end which I want to restrict.

Any inputs whats missing here.

Thanks


const validEntries = ['abc', 'ABC', 'Abc123', '123a', 'Abc_12', 'Abc_12_3a'];
const invalidEntries = ['_abc', 'abc_', '_abc_'];

const regex = /^(?!\_)(?!_*_$)[a-zA-Z0-9_]+$/;

validEntries.forEach((x) => {
  const ret = regex.test(x);
  
  console.log('Should be true :', ret);
});

console.log('-------------------');

invalidEntries.forEach((x) => {
  const ret = regex.test(x);
  
  console.log('Should be false :', ret);
});

---Updated---

I am using the regex in my angularjs application.

I have created my directive as:

       .directive('restrictField', function () {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs, ctrl) {

            var regReplace,
                preset = {                   
                    'alphanumeric-spl': '\\w_./\s/g',
                    'alphanumeric-underscore': '\\w_',
                    'numeric': '0-9',
                    'alpha-numeric': '\\w'
                },
                filter = preset[attrs.restrictField] || attrs.restrictField;                

            ctrl.$parsers.push(function (inputValue) {
                regReplace = new RegExp('[^' + filter + ']', 'ig');
                if (inputValue == undefined)
                    return ''
                cleanInputValue = inputValue.replace(regReplace, '');
                if (cleanInputValue != inputValue) {
                    ctrl.$setViewValue(cleanInputValue);
                    ctrl.$render();
                }
                return cleanInputValue;
            });
        }
    }
})

I am using this in my html as:

 <input type="text" name="uname" ng-model="uname" required class="form-control input-medium" restrict-field="alphanumeric-underscore" ng-trim="false" />  
like image 205
user1563677 Avatar asked Sep 12 '25 17:09

user1563677


1 Answers

You may add another negative lookahead ((?!.*_$)) and use

^(?!_)(?!.*_$)[a-zA-Z0-9_]+$

See the regex demo. The (?!.*_$) lookahead will fail the match if after any 0+ chars other than line break chars there is a _ at the end of the string.

Alternatively, you may use a lookaround-free pattern like

^[a-zA-Z0-9]([a-zA-Z0-9_]*[a-zA-Z0-9])?$
^[a-zA-Z0-9](\w*[a-zA-Z0-9])?$

See another regex demo. This pattern matches:

  • ^ - start of string
  • [a-zA-Z0-9] - an alphanumeric char
  • ([a-zA-Z0-9_]*[a-zA-Z0-9])? - an optional sequence of
    • [a-zA-Z0-9_]* - 0 or more word chars (in JS, you may replace it with \w*)
    • [a-zA-Z0-9] - an alphanumeric char
  • $ - end of string.

Regarding the EDIT

Your patterns are out of sync with the descriptions. Considering that preset should contain a pattern to use in the replace method, try the following keeping in mind that \w matches _:

'alphanumeric-spl': '[^\\w\\s./]+', // Removes all but alnum, _ . / whitespaces
'alphanumeric-underscore': '^_+|_+$|_+(?=_)|\\W+', // Removes all _ at start/end and all _ before a _ and all but alnum and _
'numeric': '[^0-9]+',  // Removes all but digits
'alpha-numeric': '[\\W_]+'  // Removes all but alnum

And then

regReplace = new RegExp(filter, 'ig');
like image 199
Wiktor Stribiżew Avatar answered Sep 15 '25 05:09

Wiktor Stribiżew