मैं एक शब्द के अंत में *s को बदलने के लिए एक रेगेक्स लिख रहा हूं जिसमें सुपरस्क्रिप्ट संख्याएं उन तारों की गिनती का प्रतिनिधित्व करती हैं, साथ ही एक पंक्ति की शुरुआत में तारांकन और फिर एक शब्द। यानी मैं अपने फोन पर फुटनोट लिखना आसान बना रहा हूं। चीज़ लिखें → चीज़ को iOS शॉर्टकट में भेजें → रेगेक्स मैजिक → चीज़ में फ़ुटनोट मार्कर हैं।

हालांकि, चूंकि मैं जोर देने के लिए नियमित रूप से *foo bar* का उपयोग करता हूं, इसलिए मैं उन तारों को कैप्चर नहीं करना चाहता।

मैंने सोचा कि मेरे पास इस रेगेक्स के साथ था:

/**
 * (?<=\S)                  -- make sure the thing behind the capture is a not-space
 * (?<!\W\*\w([^*]|\w\*)*?) -- make sure the thing behind the capture is not a not-word character
 *                             followed by an asterisk
 *                             followed by anything that isn't an asterisk
 *                             followed by a letter followed by an asterisk
 *                             e.g. Hello *world*.
 * \*+                      -- 1+ asterisks.  The primary capture for trailing asterisks.
 * (?=[^\w*]|$)             -- make sure the thing following the capture is a not-word-not-asterisk,
 *                             and may be the end of the line
 * |                        -- OR
 * ^\*+(?=\s\S)             -- the start of a line followed by 1+ asterisks (the primary capture)
 *                             followed by a space
 *                             followed by a not-space
 */
const regex = /(?<=\S)(?<!\W\*\w([^*]|\w\*)*?)\*+(?=[^\w*]|$)|^\*+(?=\s\S)/gm;

const transform = m => {
  const superTable = [
    '⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'
  ];

  let str = [];

  // for each digit, add the character for the 1s place then divide by ten
  for (let len = m.length; len; len = (len - len % 10) / 10) {
    str.unshift(superTable[len % 10]);
  }

  return str.join('');
}

/** [input, expectedOutput] */
const testCases = [
  [`A b*** c`, `A b³ c`],
  [`A *b* c*`, `A *b* c¹`],
  [`A *b* *c* d*`, `A *b* *c* d¹`],
  [`A *b* c* d**`, `A *b* c¹ d²`],
  [`** a b c`, `² a b c`],
  [`** a b*** c`, `² a b³ c`],
  [`A *bc* d**`, `A *bc* d²`],
  [`A *b c* d**`, `A *b c* d²`],
];

const results = ['Input\t\t=>\tActual\t\t===\tExpected\t: Success'];
results.push('='.repeat(73));

for (const [input, expected] of testCases) {
  const actual = input.replace(regex, transform);
  const extraSpacing = actual.length < 8 ? '\t' : '';
  const success = actual === expected;
  results.push(`${input}\t=>\t${actual}${extraSpacing}\t===\t${expected}${extraSpacing}\t: ${success}`);
}

console.log(results.join('\n'));

पहले छह टेस्ट केस थे जिनका मैंने पहली बार स्क्रिप्ट लिखते समय इस्तेमाल किया था। आखिरी दो जिन्हें मैंने आज खोजा। यह पता चला है कि यह *a* (तारांकन में लिपटे एकल वर्ण) के लिए ठीक काम करता है, लेकिन *ab* या *a b* (तारांकन में लिपटे 2+ वर्ण) के लिए नहीं।

मैं अपने जीवन के लिए यह नहीं समझ सकता कि मैंने क्या गलत किया है, हालांकि स्वीकार्य रूप से मैंने यह रेगेक्स सप्ताह पहले लिखा था। मुझे संदेह है कि इसका या तो लालच या आलस्य से कोई लेना-देना है, लेकिन मुझे यकीन नहीं है कि कहाँ है।

3
dx_over_dt 12 अक्टूबर 2021, 20:55
मैं सरल नियमित अभिव्यक्तियों का उपयोग करके रेखा को टोकननाइज़ कर दूंगा। सबसे पहले, प्रमुख तारों को पहचानें। फिर लाइन के भीतर *[class] को एक टोकन के रूप में पहचानें जो कुछ उपयुक्त वर्ण वर्ग के लिए जोर देना शुरू करता है और [class]* एक जोर अंत के रूप में। दो या दो से अधिक तारक वाला एक समान टोकन फुटनोट टोकन होगा। पिछले जोर सलामी बल्लेबाज से मेल नहीं खाने वाले जोर अंत को एक तारक फुटनोट के रूप में माना जाता है।
 – 
Kaz
13 अक्टूबर 2021, 00:16

1 उत्तर

सबसे बढ़िया उत्तर

आप उपयोग कर सकते हैं

/^\*+(?=\s+\S)|(?<!\s)(?<!\*(?=\S)[^*]*)(\*+)(?![\w*])/gm

रेगेक्स डेमो देखें। विवरण:

  • ^ - एक लाइन की शुरुआत
  • \*+(?=\s+\S) - एक या अधिक तारांकन के बाद एक या अधिक रिक्त स्थान और फिर एक गैर-व्हाट्सएप वर्ण
  • | - या
  • (?<!\s) - तुरंत बाईं ओर, कोई व्हाइटस्पेस चार नहीं हो सकता (यदि आपने शब्द वर्णों के साथ काम किया है, \w, तो आप यहां \b का उपयोग कर सकते हैं)
  • (?<!\*(?=\S)[^*]*) - तुरंत बाईं ओर, कोई * नहीं हो सकता है जिसके बाद एक गैर-व्हाट्सएप चार और फिर तारक के अलावा शून्य या अधिक वर्ण हों
  • \*+ - एक या अधिक तारांकन
  • (?![\w*]) - तुरंत दाईं ओर, कोई शब्द और * वर्ण नहीं हो सकते।

यहां आपका अपडेट किया गया जावास्क्रिप्ट डेमो है:

const regex = /^\*+(?=\s+\S)|(?<!\s)(?<!\*(?=\S)[^*]*)(\*+)(?![\w*])/gm;

const transform = m => {
  const superTable = [
    '⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'
  ];

  let str = [];

  // for each digit, add the character for the 1s place then divide by ten
  for (let len = m.length; len; len = (len - len % 10) / 10) {
    str.unshift(superTable[len % 10]);
  }

  return str.join('');
}

/** [input, expectedOutput] */
const testCases = [
  [`A b*** c`, `A b³ c`],
  [`A *b* c*`, `A *b* c¹`],
  [`A *b* *c* d*`, `A *b* *c* d¹`],
  [`A *b* c* d**`, `A *b* c¹ d²`],
  [`** a b c`, `² a b c`],
  [`** a b*** c`, `² a b³ c`],
  [`A *bc* d**`, `A *bc* d²`],
  [`A *b c* d*`, `A *b c* d¹`]
];

const results = ['Input\t\t=>\tActual\t\t===\tExpected\t: Success'];
results.push('='.repeat(73));

for (const [input, expected] of testCases) {
  const actual = input.replace(regex, transform);
  const extraSpacing = actual.length < 8 ? '\t' : '';
  const success = actual === expected;
  results.push(`${input}\t=>\t${actual}${extraSpacing}\t===\t${expected}${extraSpacing}\t: ${success}`);
}

console.log(results.join('\n'));
1
Wiktor Stribiżew 13 अक्टूबर 2021, 20:34
हे। एक और बग मिला। A*. B**. हालांकि कोई बड़ी बात नहीं है।
 – 
dx_over_dt
14 अक्टूबर 2021, 08:52
1
आप कोशिश कर सकते हैं const regex = /^\*+(?=\s+\w)|\b(?<!\B\*\b[^*]*)(\*+)(?![\w*])/gm;
 – 
Wiktor Stribiżew
14 अक्टूबर 2021, 10:27