ไม่รู้จักช่องว่างสีขาวของ Dart RegExp

Aug 19 2020

ฉันกำลังพยายามใช้รูปแบบ regex สำหรับชื่อผู้ใช้ที่อนุญาตให้ใช้ตัวอักษรภาษาอังกฤษตัวอักษรภาษาอาหรับตัวเลขเส้นประและช่องว่าง

รูปแบบต่อไปนี้จะคืนค่าไม่ตรงกันเสมอหากสตริงอินพุตมีช่องว่างแม้ว่าจะรวมอยู่ในรูปแบบก็ตาม

Pattern _usernamePattern = r'^[a-zA-Z0-9\u0621-\u064A\-\s]{3,30}$';

ฉันยังลองแทนที่ \ s ด้วย "" และ \\ s แต่ regex จะไม่คืนค่าที่ตรงกันสำหรับอินพุตใด ๆ ที่มีช่องว่างอยู่เสมอ

แก้ไข: ปรากฎว่า Flutter เพิ่มอักขระ Unicode สำหรับ "Right-To-Left Mark" หรือ "Left-To-Right Mark" เมื่อใช้ฟิลด์ข้อความที่มีภาษาผสมกันซึ่งไปที่ LTR หรือ RTL เครื่องหมายเพิ่มเติมนี้เป็นอักขระ Unicode ที่เพิ่มเข้าไปในข้อความ regex ด้านบนล้มเหลวเนื่องจากอักขระเพิ่มเติมนี้ ในการแก้ไขปัญหาเพียงทำการแทนที่ทั้งหมดสำหรับอักขระเหล่านี้ อ่านเพิ่มเติมที่นี่:https://github.com/flutter/flutter/issues/56514.

คำตอบ

2 wp78de Aug 20 2020 at 03:34

นี่เป็นปัญหาที่ค่อนข้างน่ารังเกียจและควรค่าแก่การบันทึกคำตอบที่นี่

ตามที่ระบุไว้ในแหล่งที่มา :

  /// When LTR text is entered into an RTL field, or RTL text is entered into an
  /// LTR field, [LRM](https://en.wikipedia.org/wiki/Left-to-right_mark) or
  /// [RLM](https://en.wikipedia.org/wiki/Right-to-left_mark) characters will be
  /// inserted alongside whitespace characters, respectively. This is to
  /// eliminate ambiguous directionality in whitespace and ensure proper caret
  /// placement. These characters will affect the length of the string and may
  /// need to be parsed out when doing things like string comparison with other
  /// text.

แม้ว่าจะมีเจตนาดี แต่ก็อาจทำให้เกิดปัญหาได้เมื่อคุณทำงานกับรูปแบบข้อความ LTR / RTL แบบผสม (เช่นในกรณีนี้) และต้องตรวจสอบความยาวฟิลด์ที่แน่นอนเป็นต้น

แนะนำวิธีการแก้ปัญหาคือการลบทั้งหมดซ้ายขวาเครื่องหมาย :

void main() {
  final String lrm = 'aaaa \u{200e}bbbb';
  print('lrm: "$lrm" with length ${lrm.length}');
  
  final String lrmFree = lrm.replaceAll(RegExp(r'\u{200e}', unicode: true), '');
  print('lrmFree: "$lrmFree" with length ${lrmFree.length}');
}

ที่เกี่ยวข้อง: ขวาไปซ้าย (RTL) ในการกระพือ