Câu hỏi Javascript regex trở lại đúng .. sau đó sai .. sau đó đúng .. vv [trùng lặp]


Câu hỏi này đã có câu trả lời ở đây:

Tôi có một vấn đề lạ với việc xác nhận tôi đang viết trên một biểu mẫu. Đó là nút 'Kiểm tra tên người dùng' bên cạnh đầu vào. Giá trị mặc định đầu vào là tên người dùng ví dụ 'betamax'. Khi tôi bấm 'Kiểm tra Tên người dùng', nó chuyển qua regex và gửi tên người dùng đến máy chủ. Máy chủ hoạt động như mong đợi và trả về '2' để báo cho javascript biết rằng họ đang gửi tên người dùng của riêng họ.

Sau đó, khi tôi nhấp vào nút một lần nữa, regex thất bại. Không có gì được gửi đến máy chủ rõ ràng vì regex đã thất bại. Nếu tôi nhấn nút một lần nữa, regex chuyển và sau đó tên người dùng được gửi đến máy chủ.

Tôi thực sự không thể hiểu được điều gì sẽ khiến nó làm điều này! Nó làm cho không có ý nghĩa với tôi!

Chỉnh sửa: Tôi đã thử nghiệm sự cố trong Firefox và Chrome (mac)

Đây là mã của tôi:

$j("#username-search").click(checkUserName);

function checkUserName() {
    var userName = $j("#username").val();


    var invalidUserMsg = 'Invalid username (a-zA-Z0-9 _ - and not - or _ at beginning or end of string)';
    var filter = /^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi;
    if (filter.test(userName)) {
        console.log("Pass")
        $j.post(
        "/account/profile/username_check/", 
        { q: userName }, 
        function(data){
            if(data == 0) {
                $j("#username-search-results").html("Error searching for username. Try again?");
            }
            else if(data == 5) {
                $j("#username-search-results").html(invalidUserMsg);
            }
            else if(data == 4) {
                $j("#username-search-results").html("Username too short or too long.");
            }
            else if(data == 2) {
                $j("#username-search-results").html("This is already your username.");
            }
            else if(data == 3) {
                $j("#username-search-results").html("This username is taken.");
            }
            else if(data == 1){
                $j("#username-search-results").html("This username is available!");
            }
        });
    } else {
        console.log("fail")
        $j("#username-search-results").html(invalidUserMsg);
    }

    return false;

}

HTML:

<input name="username" id="username" value="{{ user.username }}" />
<input type="button" value="Is it taken?" id="username-search">
<span id="username-search-results"></span>

76
2018-04-13 14:40


gốc




Các câu trả lời:


/^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi;

Bạn đang sử dụng g (toàn cầu) RegExp. Trong JavaScript, regexen toàn cầu có trạng thái: bạn gọi chúng (với exec, test vv) lần đầu tiên, bạn sẽ có được trận đấu đầu tiên trong một chuỗi nhất định. Gọi cho họ một lần nữa và bạn sẽ có được trận đấu tiếp theo, và cứ như vậy cho đến khi bạn không có trận đấu nào và nó sẽ đặt lại để bắt đầu chuỗi tiếp theo. Bạn cũng có thể viết regex.lastIndex= 0 để đặt lại trạng thái này.

(Đây tất nhiên là một thiết kế hoàn toàn khủng khiếp, đảm bảo gây nhầm lẫn và gây ra các lỗi lạ. Chào mừng bạn đến với JavaScript!)

Bạn có thể bỏ qua g từ của bạn RegExp, vì bạn chỉ đang thử nghiệm cho một kết quả phù hợp.

Ngoài ra, tôi không nghĩ bạn muốn [^-_] ở phía trước và sau. Điều đó sẽ cho phép bất kì ở mỗi đầu, ví dụ. *plop! sẽ hợp lệ. Có thể bạn đang nghĩ đến các xác nhận lookahead / lookbehind, nhưng chúng không có sẵn trong JavaScript. (Vâng, lookahead là nghĩa vụ phải được, nhưng nó bị hỏng trong IE.) Đề nghị thay vào đó:

/^[a-z0-9][a-z0-9_-]{2,18}[a-z0-9]$/i

140
2018-04-13 14:54



Tôi đã học được một cái gì đó mới ngày hôm nay! Tôi chưa bao giờ xử lý RegEx trong JS trước đây. :) - Powerlord
Đó là nó. Tôi thường bao gồm / g ra khỏi thói quen nhưng tôi đoán tôi sẽ không làm điều đó nữa! Cảm ơn! - betamax
1 Tôi muốn nói rằng nó chỉ là duy nhất cho việc sử dụng từ "regexen", nhưng đó là một câu trả lời tuyệt vời trong tất cả các khía cạnh ;-) - Andy E
@Bobince nổi tiếng! Cảm ơn bạn đã chia sẻ điều này. - maček
Tôi nghĩ phụ nữ sử dụng regex.test để cung cấp câu trả lời của họ về việc họ có hẹn hò không. - toddmo


[a-z0-9-_]

Điều này là sai, cuối cùng - phải ở đầu hoặc cuối.

[a-z0-9_-]

Cho dù điều đó có gây ra vấn đề này hay không, tôi không biết.

Ghi chú bổ sung:

Ký tự đầu tiên và cuối cùng được phép là bất kỳ ký tự nào không phải - hoặc là _ thay vì bị hạn chế a-z0-9

a-z0-9 không bao gồm các ký tự viết hoa. Bạn cần a-zA-Z0-9 cho điều đó. a-zA-Z0-9_ có thể được rút ngắn thành \w trong hầu hết các công cụ RegEx. Tôi đã không thử nó trong JavaScript.


2
2018-04-13 14:44



Cảm ơn vì tiền hỗ trợ. Tại sao lệnh chính xác lại quan trọng? Thật không may, điều đó không giải quyết được vấn đề tôi đang thấy. Tôi chỉ thử nghiệm nó trong chrome (đã được sử dụng Firefox) và nó làm điều tương tự. - betamax
-là một nhân vật đặc biệt trong các nhóm ... như bạn có thể thấy, vì bạn sử dụng nó cho a-z. Do đó, nó được định nghĩa là chỉ là một chữ - là ký tự đầu tiên hoặc cuối cùng của RegEx. Có nói rằng, bạn có thể cần phải chuyển đổi nó trong [^-_] là tốt (để [^_-]). - Powerlord
Rất tiếc, tôi mới nhận thấy tôi đã đặt /w thay vì \w trong câu trả lời của tôi. Nên được cố định ngay bây giờ. - Powerlord
Tôi có lá cờ 'i' ở cuối RegEx khiến nó không phân biệt chữ hoa chữ thường. Một lỗ hổng khác mà tôi đã nhận thấy trong RegEx là nó chấp nhận bất cứ thứ gì BUT - hoặc _ ở đầu chuỗi (ví dụ: betamax £ sẽ hợp lệ). Vì vậy, để xem xét và sửa chữa được đề cập bởi bobince, RegEx cuối cùng là /^[a-z0-9]([a-z0-9_-]{4,20})[a-z0-9]$/i - betamax
Bạn có thể sử dụng cách khác \- để đặt một dấu gạch nối chữ ở bất kỳ đâu trong một nhóm ký tự. Cách tiếp cận này có lẽ dễ đọc hơn! Vâng, theo tiêu chuẩn regex ... @ betamax: vâng, chỉ cần phát hiện ra bản thân mình và thêm nó vào! :-) - bobince