عبارت منظم/جاوااسکریپت: تقسیم رشته به خطوط جداگانه بر اساس حداکثر تعداد کاراکتر در هر خط با نگاه کردن n کاراکتر به عقب برای یافتن یک فاصله ممکن؟
این سوال مشابه سوال "چگونه یک رشته را هر n کاراکتر یا نزدیکترین فاصله قبلی تقسیم کنیم" است، اما برخلاف آنچه بر اساس عنوان انتظار داشتم، آن راهحل در صورتی که تنها یک کلمه بلند بدون هیچ فاصلهای وجود داشته باشد کار نمیکند.
پس من به یک عبارت منظم نیاز دارم که یک رشته را به خطوط جداگانه تقسیم کند (در صورت نیاز چندین بار) بر اساس حداکثر تعداد کاراکتر در هر خط، و به عقب نگاه کند n کاراکتر برای پیدا کردن یک فاصله ممکن (اگر پیدا شد در آنجا شکست بخورد، در غیر این صورت در طول حداکثر)؟
ویرایش 1: به عنوان مثال، با حداکثر طول خط 30 کاراکتر و جستجوی فضای خالی به عقب 15 کاراکتر:
لورم ایپسوم فقط متن ساختگی صنعت چاپ و صفحهآرایی است.
کلمه اول آن جمله طولی برابر با ۳۲ کاراکتر دارد. بنابراین خروجی باید این باشد:
Loremipsumissimplydummytextoft # Line has length of 30 char
he printing and typesetting # Cut before the word at otherwise 30 char
industry.
بنابراین اولین کلمه باید پس از کاراکتر سیام بهاجبار بریده شود، زیرا هیچ فاصلهای وجود نداشت.
رشته باقیمانده طولی معادل ۲۸ (یا ۲۹ با خط فاصله) قبل از کلمه 'industry' دارد، بنابراین در موقعیت کاراکتر سیام یک کلمه قرار دارد، بنابراین راهحل به دنبال فاصله سفید قبلی در بازه ۱۵ کاراکتر میگردد. آن خط قبل از کلمه 'industry' شکسته میشود.
ویرایش ۲: دومین نمونه متن:
لورم ایپسوم صرفاً متن ساختگی صنعت چاپ و صفحهآرایی است. لورم ایپسوم صرفاً متن ساختگی صنعت چاپ و صفحهآرایی است. لورم ایپسوم صرفاً متن ساختگی صنعت چاپ و صفحهآرایی است. لورم ایپسوم صرفاً متن ساختگی صنعت چاپ و صفحهآرایی است.
باید خروجی دهد:
Loremipsumissimplydummytextoft
he printing and typesetting
industry. Loremipsumis simply
dummytext ofthe printing and
typesetting industry.
Loremipsumissimplydummytextoft
he printing and typesetting
industry. Loremipsumis simply
dummytext ofthe printing and
typesetting industry.
کاربرد این عبارت منظم (regex) برای قالببندی یک رشته طولانی به متن قابل خواندن با حداکثر طول خط اعمال شده و خطوطی که با یک کاراکتر شروع میشوند و نه یک فاصله سفید است.
نیاز اختیاری: وقتی پس از ارسال اولیه آن مثال را در ویرایش ۱ اضافه کردم، یک نیاز اختیاری نیز برای افزودن کاراکتر خط تیره '-' در ابتدای خط بعد، اگر یک کلمه در حداکثر طول خط بریده شده بود، اضافه کردم. اکنون آن را از مثال حذف کرده و به عنوان یک نیاز اختیاری جداگانه اینجا اضافه میکنم.
پس یک الزامات اختیاری: اگر یک خط در وسط یک کلمه در طول حداکثر شکسته شود و در فاصله نباشد، باید خط تیره در انتهای آن خط اضافه شود (و نه در ابتدای خط بعدی، همانطور که من در ابتدا توضیح داده بودم).
Loremipsumissimplydummytextoft- # Line length 30+1 char with an appended a dash
he printing and typesetting # Cut before the word at otherwise 30 char
industry.
پاسخ شماره ۱
شما میتوانید استفاده کنید
var s = "Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry. Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry.";
var regex = /\s*(?:(\S{30})|([\s\S]{1,30})(?!\S))/g;
console.log(
s.replace(regex, function($0,$1,$2) { return $1 ? $1 + "-\n" : $2 + "\n"; } )
)جزئیات
\s*- صفر یا بیشتر کاراکترهای فاصله.(?:- شروع گروه بدون گرفتن:(\S{30})- گروه ۱ (با استفاده از متغیر$1در متد callback مورد اشاره قرار میگیرد): سی (n) کاراکتر غیر فاصلهای
|- یا([\s\S]{1,30})(?!\S))- گروه ۲ (که در متد callback با متغیر$2به آن ارجاع داده میشود): هر یک تا سی کاراکتر (n)، تا حد امکان، اما بلافاصله پس از آن با یک کاراکتر غیر فاصله دنبال نشود.
قسمت function($0,$1,$2) { return $1 ? $1 + "-\n" : $2 + "\n"; } به این معنی است که اگر گروه 1 مطابقت داشته باشد (یعنی ما یک کلمه بسیار طولانی را پیدا کردهایم که به دو قسمت تقسیم شده است)، ما تطابق را با مقدار گروه 1 + خط تیره و یک خط جدید جایگزین میکنیم. در غیر این صورت، اگر گروه 2 مطابقت داشته باشد، آن را با مقدار گروه 2 + یک خط جدید جایگزین میکنیم.
قطعه کد مطابق با ES6+:
const text = "Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry. Loremipsumissimplydummytextofthe printing and typesetting industry. Loremipsumis simply dummytext ofthe printing and typesetting industry.";
const lineMaxLen = 30;
const wsLookup = 15; // Look backwards n characters for a whitespace
const regex = new RegExp(String.raw`\s*(?:(\S{${lineMaxLen}})|([\s\S]{${lineMaxLen - wsLookup},${lineMaxLen}})(?!\S))`, 'g');
console.log(
text.replace(regex, (_, x, y) => x ? `${x}-\n` : `${y}\n`)
);پاسخ شماره ۲
پاسخ نهایی:
(\S[\s\S]{1,30}$|\S[\s\S]{1,29}(?:\s+)|\S{30})
تکامل :
- ([\s\S]{1,15}(?!\S)|\S{15,})
شما فقط باید پاسخ در لینک را با یک عبارت 'یا' که نیاز اضافی شما را اضافه میکند تغییر دهید: |\S{15,}
- در پاسخ به ویرایشهای شما، این عبارت منظم اصلاحشده من است: ([\s\S]{1,15}(?!\S)|\S{15})
شما میتوانید ۱۵ ثانیه را با ۳۰ یا هر حد کاراکتری که میخواهید جایگزین کنید
- تنظیم بر اساس توضیحات بیشتر شما: (\S[\s\S]{1,14}(?:\s*)|\S{15})
حالا رشته باید با یک کاراکتر غیر فاصله شروع شود و مطابقت میکند اما فاصلههای اضافی بعد از ۱۵ کاراکتر اول را ضبط نمیکند. دوباره باید ۱۵ و ۱۴ را به طولهایی که میخواهید تغییر دهید.
- (\S[\s\S]{1,30}$|\S[\s\S]{1,29}(?:\s+)|\S{30}) افزودن یک شرط دیگر در عبارت چندگانه 'یا' در ابتدای آن که انتهای رشته را در صورتی که با یک کاراکتر غیر فاصله تمام شود، میگیرد. اگر با یک کاراکتر فاصله پایان یابد، قسمت دوم عبارت 'یا' آن را میگیرد.
