-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
moustafa
دستتون درد نکنه جناب بهرامی عزیز
در متون فارسی هم کارایی داره ؟
نقل قول:
نوشته شده توسط
eb_1345
خواهش میکنم
امتحان نکرده ام ولی به احتمال زیاد در متون فارسی هم باید کارائی داشته باشه .
ان شاء الله به کمک دوستان در ادامه مثال ها و نمونه های کاربردی اعم از فارسی یا انگلیسی رو بررسی و امتحان می کنیم
دوستان ! در ارتباط با متون فارسی بنده چند موردی رو امتحان کردم خوشبختانه جواب داد. البته ناگفته نمونه ممکنه بعضی از علامت هائی که در عبارت الگو بکار برده میشه برای متون فارسی کاربرد نداشته باشه .
در هر حال اگه مواردی مورد نظرتونه امتحان کنین و اگه هم به نتیجه نرسیدین مورد رو در اینجا مطرح کنین تا بررسی بشه .
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
استفاده از Regex Tester
برای تست کردن درستی regex های خودتون میتونین از سایتهای آنلاین هم استفاده کنین. برای این منظور میتونین از دو سایت های مهم در لینک های زیر استفاده کنین :
1 سایت: regexr.com
2- سایت: regex101.com
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
یک نکته ظریف در خصوص استفاده از علامت براکت []
در قواعد ریجکس علامت [] بعتوان مجموعه ای از کاراکترها شناخته میشه. یک مثال میزنم که موضوع روشنتر بشه .
فرض می کنیم یک متنی انگلیسی داریم و میخواهیم بفهمیم که آیا در این متن کلمه مثلاً book وجود داره یا نه . برای اینکار باید این کلمه رو مستقیماً در قسمت عبارت پترن وارد می کنیم تا نتیجه جستجو درست باشه و اگه همین کلمه رو داخل علامت [] بذاریم نتیجه درست حاصل نمیشه چرا که وقتی کلمه در داخل براکت قرار گرفت اون کلمه بعنوان یک مجموعه از کاراکترها مورد بررسی و جستجو قرار میگیره ، بعبارتی هر کدوم از کاراکترها بصورت جدا جدا جستجو میشه .مثلاً ممکنه در متن 50 حرف b یا 30 تا حرف o یا 20 تا حرف k در متن باشه و در نتیجه جستجو همه اونها انتخاب میشن ولی اگه book بدون استفاده از علامت براکت و مستقیماً در عبارت الگو یا پترن درج بشه در متن خود کلمه book جستجو میشه نه کاراکترهای اون بصورت جداجدا
برای متن فارسی هم به همین صورته
برای اثبات این موضوع از همون فرم تست الگو نمونه پست 36 استفاده کنین ! در تکست باکس متن جمله من بهرامی هستم رو وارد کنید و در تکست باکس پترن هم بهرامی ، بعد بر روی باتن تست الگو کلیک کنین ! مشاهده خواهین کرد که در لیست باکس پائین یک مورد تطبیق با رشته بهرامی نمایش داده میشه ؛ حالا بهرامی رو داخل براکت درج کنین و امتحان کنین ! در این حالت 9 مورد کارکتر ب ه ر ا م ی در لیست باکس نمایش داده میشه
-
validation تاریخ خورشیدی با RegEx و VBA
با اجازه استارتر محترم تاپیک و در تکمیل بخش مربوط به پترن تاریخ خورشیدی:
1- یک پترن کامل همراه با کد در پست شماره 35 جناب آقای بهرامی هست.
2- موردی هم هست که در پست شماره 39 اشاره کردم:
نقل قول:
اگر بخواهیم فقط با یک پترن چک کنیم گاهی پترن خیلی پیچیده میشه،
که هم نوشتنش سخت و زمانبر هست و هم نگهداریش و دیباگ کردنش.
ولی اگر از کد هم کمک بگیریم میونیم پروسه رو به بخش های کوچک تری بشکنیم
که هم نوشتنش و هم نگهداری و دیباگش ساده تر است ،
و چه بسا پرفورمنس بهتری هم داشته باشه.
الزاما و در همه جا سپردن همه چیز به regex با پترن های پیچیده،
نتیجه بهتری از کدهای ساده تر بدست نمیده و گاهی اصلا نباید از regex استفاده کرد (این رو در پست جدا بیشتر باز میکنم).
در موردن validation تاریخ خورشیدی،
یک بخش خود ساختار تاریخ هست که با regex بتنهایی شدنی هست (پست شماره 35).
ولی اگر نیاز به اطلاعات تکمیلی باشه مانند دلیل خطا،
باید کد بیشتری استفاده کنیم.
ابتدا یک udt به اسم PersianDate تعریف کردیم که تابع مورد نظر ما CheckPersianDate از همین جنس خواهد بود:
Public Type PersianDate
YYYY As Long
MM As Long
DD As Long
IsValid As Boolean
ErrorText As String
End Type
در اینجا بجای یک پترن پیچیده از 2 پترن ساده استفاده کردیم؛
یکی برای حالتی که تاریخ فرمت نشده هست (بدون /) ،
و یکی برای حالتی که از / برای جدا کردن بخش های تاریخ استفاده شده.
در خود تابع این امکان رو فراهم کردیم که کاربر مشخص کنه تاریخ فرمت شده هست یا نه،
و همچنین حالتی که مشخص نیست (don't care) - یعنی تشخیص شکل تاریخ رو به عهده تابع میگذاریم و با هر کدوم که بخونه کار میکنه.
Public Enum IsDelimited
DontCare = 0
YES = 1
NO = 2
End Enum
Const DateNotDelimited As String = "^(\d{4})(\d{2})(\d{2})$"
Const DateDelimited As String = "^(\d{4})/(\d{2})/(\d{2})$"
Public Function CheckPersianDate( _
DateStr As String, _
Optional Is_Delimited As IsDelimited = IsDelimited.DontCare) _
As PersianDate
Dim mc As MatchCollection
With New RegExp
Select Case Is_Delimited
Case IsDelimited.NO
.Pattern = DateNotDelimited
Case IsDelimited.YES
.Pattern = DateDelimited
Case Else ' dont care
.Pattern = DateDelimited
If Not .test(DateStr) Then
.Pattern = DateNotDelimited
End If
End Select
Set mc = .Execute(DateStr)
End With
With CheckPersianDate
If mc.Count = 0 Then
.YYYY = -1
.MM = -1
.DD = -1
.IsValid = False
.ErrorText = "Invalid PersianDate Structure"
Exit Function
End If
Dim m As Match
Set m = mc(0)
.IsValid = True
.YYYY = m.SubMatches(0)
.MM = m.SubMatches(1)
.DD = m.SubMatches(2)
If .YYYY < 1300 Or .YYYY > 1499 Then
.IsValid = False
.ErrorText = "Invalid Year"
Else
Select Case .MM
Case 1 To 6
If .DD < 1 Or .DD > 31 Then
.IsValid = False
.ErrorText = "Invalid Day of Month"
End If
Case 7 To 11
If .DD < 1 Or .DD > 30 Then
.IsValid = False
.ErrorText = "Invalid Day of Month"
End If
Case 12
If .DD < 1 Or .DD > 29 Then
.IsValid = False
.ErrorText = "Invalid Day of Month"
End If
Case Else
.IsValid = False
.ErrorText = "Invalid Month"
End Select
End If
End With
End Function
-
validation کد ملی با RegEx
با اجازه استارتر محترم تاپیک؛
البته validation کد ملی بدون regex هم کار ساده ای هست.
ولی اینجا برای نشون دادن یک کاربرد ویژه، اون رو در این مسئله به کار میبریم.
Public Function IsValidSSID(SSID As Variant) As Boolean
Select Case VarType(SSID)
Case vbString, vbInteger, vbLong, vbDecimal, vbLongLong, vbSingle, vbDouble
SSID = Format(SSID, String(10, "0"))
Case Else
IsValidSSID = False
Exit Function
End Select
With New RegExp
.Pattern = "(.)\1{9}"
If .test(SSID) Then
IsValidSSID = False
Exit Function
End If
End With
Dim Digits As MatchCollection
With New RegExp
.Pattern = "\d"
.Global = True
Set Digits = .Execute(SSID)
End With
Dim i As Integer
Dim sum As Integer
For i = 0 To 8
sum = sum + Digits(i) * (10 - i)
Next
Dim r As Integer
r = sum Mod 11
If r < 2 Then
IsValidSSID = (Digits(9) = r)
Else
IsValidSSID = (Digits(9) = 11 - r)
End If
End Function
1- نوع پارامتر کد ملی SSID به string محدود نشده،
و اجازه میدیم کاربر هر مقداری رو بتونه به تابع پاس بده،
ولی در تابع فقط مقادیر string و عددی رو قبول میکنیم.
2- با یک تابع format ، سمت چپ string تا 10 کاراکتر رو با 0 پر میکنیم.
3- موضوع کاربردی اینجاست:
.Pattern = "(.)\1{9}"
در واقع الگوریتم انتخاب شده برای کد ملی یک اشکال داره و اونهم این هست که
اگر همه ارقام یکی باشن معتبر نشون میده (البته در واقعیت ما باید از یک api استفاده کنیم و کد ملی رو با سایر مشخصات تطبیق بدیم).
در این پترن از چیزی استفاده کردیم که بهش back-reference میگن و برای capture group شماره 1 - 9 بار تکرار میشه (جمعا 10 بار).
وگرنه میبایست همه این 10 حالت رو چک میکردیم - حالا یا یکی یکی یا در یک حلقه.
4- به جای چرخیدن در SSID و خوندن هر رقم با $mid ، مستقیما از match collection ارقام رو میخونیم و محاسبه میکنیم.
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
mazoolagh
با اجازه استارتر محترم تاپیک؛
اجازه ماهم دست شماست استاد گرامی !
ممنون از همراهی و ارائه مطالب مفیدتون !
-
کجا نباید از regex استفاده کرد؟
نقل قول:
الزاما و در همه جا سپردن همه چیز به regex با پترن های پیچیده،
نتیجه بهتری از کدهای ساده تر بدست نمیده و گاهی اصلا نباید از regex استفاده کرد (این رو در پست جدا بیشتر باز میکنم).
1- وقتی که string ما ساختار پیچیده و تو در تو داره - مثل html , xml , json یا کدهای برنامه نویسی و .. ،
برای این چیزها باید از parser استفاده کرد که همه اینها دارن و نیازی نیست که دوباره چرخ رو اختراع کنیم.
یک تاپیک دقیقا مربوط به همین وضعیت هست که میتونین با خوندن اون پی ببرین چجوری استفاده از regex بجای parser شما رو به بیراهه میبره:
یک لیست از کلمات کلیدی و تشخیص آن در متن
و روش درست انجام کار با parser مناسب:
تفسیر و آنالیز سورس SQL با استفاده از Microsoft.SqlServer.TransactSql.ScriptDom
2- وقتی stringهای بزرگ،
یا لوپ های سنگین داریم، regex میتونه به شدت روی پرفورمنس تاثیر بگذاره.
3- وقتی با دیتا انکود شده یا غیر text (binary) سروکار داریم.
4- وقتی ساختار دیتا خیلی گسترده باشه، چون نوشتن و خوانایی و نگهداری برنامه سخت و پیچیده میشه.
یک مورد دیگه هم هست که از نظر امنیتی اهمیت پیدا میکنه:
و اون وضعیتی هست که یک پترن بد یا ورودی بد داریم
جوری که انجین regex در لوپ گرفتار میشه و با مصرف منابع سیستم (cpu/ram) سیستم رو دچار overload میکنه که نهایتا ممکنه crash کنه.
برای همین همیشه باید هم اندازه دیتا ورودی رو محدود کرد و هم یک بررسی اولیه روی اون انجام داد.
برای اطلاعات بیشتر جستجو کنین: ReDoS (Regular Expression Denial of Service)
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
eb_1345
اجازه ماهم دست شماست گرامی !
ممنون از همراهی و ارائه مطالب مفیدتون !
شرمنده که تاپیک از آموزش به گفتگو تبدیل شد،
ولی چراغی که شما روشن کردین به یکی از انگشت شمار تاپیک های با موضوع نو و به انجام رسیده اینجا تبدیل شد.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
یکی دیگه از کاربردهای RegEx انجام عمل جایگزین کردن یا Replace می باشه . همانطور که میدونیم در متد Replace در یک رشته یا متن یک مقدار مشخص جایگزین مقدار مشخص دیگه ای میشه که با استفاده از تابع Replace اینکار انجام میشه
در مثال زیر فرض می کنیم در عبارتی که در Text1 وارد شده میخواهیم بجای کلمه loop از کلمه lop استفاده کنیم
Text1 = "yadda yadda {1:NM:=12.000:0.120} omtty doom loop{1:NM:=6/6} loppy loop"
از تابع Replace بصورت زیر استفاده می کنیم :
Text1 = Replace(Text1, "loop", "lop")
حالا اگه در متن فوق قرار باشه بجای علامت آکولاد باز وبسته {} و هر کاراکتری که در درون اون وجود داره یک مقدار خاصی جایگزین کنیم آیا در این حالت هم براحتی میشه از تابع Replace بصورت معمولی استفاده کرد؟
در مثال بالا عمل جایگزینی در سرتاسر متن انجام میشه یعنی در سرتاسر متن کلمه lop جایگزین کلمه loop میشه .اما ما میخواهیم مقدار جدید جایگزین علامت آکولاد باز وبسته {} و هر کاراکتری که در درون اون قرار داره بشه . در داخل علامت آکولاد باز وبسته {} ممکنه هر کاراکتری و به هر تعدادی وجود داشته باشه.
بی تردید در این حالت که عمل جایگزینی باید براساس قواعد و شرط و شروط خاصی صورت میگیره لازمه از RegEx کمک گرفته بشه و برای انجام اینکار یک پترن مناسب تهیه کرد.
پترنی که علامت آکولاد باز وبسته {} و کاراکتری داخل اون رو انتخاب میکنه بصورت زیر می باشه :
\{.*?\}
حالا این پترن چی میگه ؟ میگه در متن برو دنبال مقداری بگرد که اولش با علامت } شروع شده باشه }\ بعد از علامت آکولاد باز هر کاراکتری رو انتخاب کن برای هر کاراکتر از کاراکتر نقطه استفاده می کنیم و برای به هر تعداد(صفر یا بیشتر ) از علامت ستاره * استفاده می کنیم بعد از علامت ستاره علامت ? اضافه می کنیم و با درج این علامت میگیم اگه هیچ کاراکتری هم اگه نبود اشکال نداره ، شرط آخرمون هم اینکه مقدار با علامت آکولاد بسته { خاتمه پیداکنه{\
حالا بجای این مقداری که با قاعده فوق مشخص کردیم میخواهیم مقدار فرضا عدد 9 رو جایگزین کنیم .
خلاصه برای اجرای عمل جایگزینی فوق از کد زیر استفاده می کنیم :
Dim regEx As Object
Dim html_input As String
Set regEx = CreateObject("VBScript.RegExp")
regEx.Pattern = "\{.*?\}"
regEx.Global = True
Text1 = regEx.Replace(Text1, "9")
در نتیجه رشته خروجی yadda yadda 9 omtty doom 9 loppy loop می باشه
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
درود بر جناب آقای بهرامی گرامی که مثل همیشه مطالب تخصصی را بسیار ساده و قابل فهم توضیح میدهند.
از جناب mazoolagh عزیز هم بخاطر ارائه نظرات تخصیصی قدردانی میشود.
درود بر هر دو بزرگوار
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
برای اینکه متوجه بشیم مطالب آموزشی تا اینجا برای دوستان علاقمند مفید فایده بوده در این پست سوالی ساده طرح می کنیم
با توجه به توضیحات پست 49 میخواهیم یک پترن بنویسیم که در متن انگلیسی زیر کلماتی که حرف آخرشون e میباشه بجای حرف e آخر کلمه عدد 9 جایگزین بشه . مثل کلمه home به hom9 تبدیل بشه.
تاکید می کنم این جایگزینی فقط باید در کلماتی که حرف آخرشون e میباشه صورت بگیره نه کلماتی که حرف e در اول یا وسطشون می باشه
برای تست از کدهای پست 49 استفاده کنین!
Social media star Peanut the Squirrel has been euthanized after being seize from NY home
قطعاً جواب این سوال برای دوستانی که مطالب ارائه شده رو با دقت مرور کرده ان بسیار ساده خواهد بود .
متن خروجی باید بصورت زیر باشه :
Social media star Peanut th9 Squirrel has been euthanized after being seiz9 from NY hom9
-
1 ضمیمه
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نسخه آپدیت شده برنامه نمونه
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
mazoolagh
3- موضوع کاربردی اینجاست:
.Pattern = "(.)\1{9}"
در واقع الگوریتم انتخاب شده برای کد ملی یک اشکال داره و اونهم این هست که
اگر همه ارقام یکی باشن معتبر نشون میده (البته در واقعیت ما باید از یک api استفاده کنیم و کد ملی رو با سایر مشخصات تطبیق بدیم).
در این پترن از چیزی استفاده کردیم که بهش back-reference میگن و برای capture group شماره 1 - 9 بار تکرار میشه (جمعا 10 بار).
وگرنه میبایست همه این 10 حالت رو چک میکردیم - حالا یا یکی یکی یا در یک حلقه.
.
با سلام و وقت بخیر
در تابع فوق نمیشه از طریق کد زیر تکراری بودن 10 رقم کد ملی رو چک کرد؟
If Len(SSID) - Len(Replace(SSID, Left(SSID, 1), "")) = 10 Then
IsValidSSID = False
Exit Function
End If
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
eb_1345
با سلام و وقت بخیر
در تابع فوق نمیشه از طریق کد زیر تکراری بودن 10 رقم کد ملی رو چک کرد؟
If Len(SSID) - Len(Replace(SSID, Left(SSID, 1), "")) = 10 Then
IsValidSSID = False
Exit Function
End If
سلام دوباره
قطعا میشه،
این دست شماست که چه روشی پیاده کنین.
گاهی در حالتهایی خاص (مثل اینجا که تکراری بودن شامل همه استرینگ هست) میشه کدهایی شبیه این نوشت،
یا حتی کوتاهترش کرد:
If Replace(SSID, Left(SSID, 1), "")="" Then
IsValidSSID = False
Exit Function
End If
شما هر کاری رو که با regex انجام میدین،
با همین توابع string و split و ... هم میشه.
گاهی حتی ساده تر هم هست (پست 44)، و خب گاهی ممکنه خیلی سخت تر باشه - ولی میشه.
به طور مطلق نمبتونین بگین کدوم برتری داره: در سناریو هست که با توجه به شرایط مشخص میشه.
در همین مثال اگر مسئله به این صورت تغییر کنه:
آیا یک استرینگ شامل حروف تکراری (2 یا بیشتر) پشت سر هم هست؟
مثل abcdddefgghhhhxyyyxx که باید اینها رو پیدا کنه: abcdddefgghhhhxyyyxx
دیگه کدی که فقط با توابع استرینگ پیاده شده باشه، شاید نوشتنش به سادگی این مثال نباشه (همیشه شدنی هست)
ولی همین روش back-refrence با یک پترن ساده پاسخگو هست:
(.)\1+
دیگه انتخابش با شماست که یک Trade-off بین زمان رسیدن به پاسخ، سادگی نگهداری و دیباگ، خوانایی، پرفورمنس و ... انجام بدین.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
در پست شماره 34 یک بخش هست که چند بار میخواستم بپرسم و فراموش کردم:
نقل قول:
البته در متن انگلیسی برای بدست آوردن تعداد یک کاراکتر یا کلمه خاص در یک متن میتونیم با ترکیب تابع Len و Replace اینکار رو انجام بدهیم
مثلاً در همون مثال اولی میخواهم تعداد حرف o رو در متن
www.bahrami125@yahoo.com ورودی بدست بیاریم.
برای اینکار تابع رو بصورت زیر مینویسیم :
CountWords = Len("www.bahrami125@yahoo.com") - Len(Replace("www.bahrami125@yahoo.com", "o", ""))
ولی با این کد تعداد در متون فارسی درست بدست نمیاد ولی تابعی که در اون از پترن استفاده شده برای بدست آوردن تعداد در هر دو حالت فارسی و انگلیسی مناسبتره
این بخش رو میشه بیشتر توضیح بدین که روی چه استرینگ هایی تست کردین که جواب نداده؟
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
در پست شماره 34 یک بخش هست که چند بار میخواستم بپرسم و فراموش کردم:
این بخش رو میشه بیشتر توضیح بدین که روی چه استرینگ هایی تست کردین که جواب نداده؟
با عرض سلام
لطفاً مورد زیر رو امتحان بفرمائید!
MsgBox Len("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....") - Len(Replace("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....", "حالي", ""))
البته ناگفته نمونه که تعداد خروجی همیشه هم اشتباه نیست . شاید استفاده از تابع Trim برای آرگومان مقدار مورد جستجو مشکل رو برطرف کنه
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
eb_1345
برای اینکه متوجه بشیم مطالب آموزشی تا اینجا برای دوستان علاقمند مفید فایده بوده در این پست سوالی ساده طرح می کنیم
با توجه به توضیحات پست 49 میخواهیم یک پترن بنویسیم که در متن انگلیسی زیر کلماتی که حرف آخرشون e میباشه بجای حرف e آخر کلمه عدد 9 جایگزین بشه . مثل کلمه home به hom9 تبدیل بشه.
تاکید می کنم این جایگزینی فقط باید در کلماتی که حرف آخرشون e میباشه صورت بگیره نه کلماتی که حرف e در اول یا وسطشون می باشه
برای تست از کدهای پست 49 استفاده کنین!
Social media star Peanut the Squirrel has been euthanized after being seize from NY home
قطعاً جواب این سوال برای دوستانی که مطالب ارائه شده رو با دقت مرور کرده ان بسیار ساده خواهد بود .
متن خروجی باید بصورت زیر باشه :
Social media star Peanut th9 Squirrel has been euthanized after being seiz9 from NY hom9
باسلام
فکر کنم باید از پترن زیر استفاده کنیم
[e]\b
برای حل این مسئله از مثال مربوط به علامت \b در فایل نمونه اسفاده کردم.
نقل قول:
نوشته شده توسط
mazoolagh
شما هر کاری رو که با regex انجام میدین،
با همین توابع string و split و ... هم میشه.
گاهی حتی ساده تر هم هست (پست 44)، و خب گاهی ممکنه خیلی سخت تر باشه - ولی میشه.
به طور مطلق نمبتونین بگین کدوم برتری داره: در سناریو هست که با توجه به شرایط مشخص میشه.
بنده هر کاری کردم نتوانستم مسئله بالا رو از طریق توابع string و split حل کنم . اگر استاد راهنمائی کنن که از طریق توابع فوق به چه صورتی باید برای حل مسئله فوق استفاده کنیم ممنون میشوم
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
با عرض سلام
لطفاً مورد زیر رو امتحان بفرمائید!
MsgBox Len("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....") - Len(Replace("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....", "حالي", ""))
البته ناگفته نمونه که تعداد خروجی همیشه هم اشتباه نیست . شاید استفاده از تابع Trim برای آرگومان مقدار مورد جستجو مشکل رو برطرف کنه
سلام دوباره
استرینگ ها در اکسس یونیکد نگهداری میشن و توابع استرینگ و regex به زبان حساس نیست.
اونچه برداشت میکنم این هست که شما دنبال تعداد "حالی" هستین، که 4 حرفی هست،
ولی کد پست 34 برای یک استرینگ یک کارآکتری درست کار میکنه - در واقع یک حالت خاص هست.
شما باید اندازه استرینگی رو که دنبالش هستین در محاسبات بیارین:
PUBLIC FUNCTION CountOf( _
Expression AS STRING, _
Find AS STRING _
) AS INTEGER
DIM LenE AS INTEGER, LenF AS INTEGER
LenE=LEN(Expression)
LenF=LEN(Find)
IF LenF=0 OR LenE=0 THEN
CountOf=0
ELSE
CountOf=(LenE - LEN(REPLACE(Expression , Find , "")))/LenF
ENDIF
END FUNCTION
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
با عرض سلام
لطفاً مورد زیر رو امتحان بفرمائید!
MsgBox Len("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....") - Len(Replace("در حالي که من با چشم هاي خودم ديدم و اين در حالي بود که ....", "حالي", ""))
البته ناگفته نمونه که تعداد خروجی همیشه هم اشتباه نیست . شاید استفاده از تابع Trim برای آرگومان مقدار مورد جستجو مشکل رو برطرف کنه
روش های دیگه هم میشه به کار برد:
PUBLIC FUNCTION CountOf( _
Expression AS STRING, _
Find AS STRING _
) AS INTEGER
IF LEN(Find)=0 OR LEN(Expression)=0 THEN
CountOf=0
ELSE
DIM X AS VARIANT
X=SPLIT(Expression , Find)
CountOf=UBOUND(X)
ENDIF
END FUNCTION
PUBLIC FUNCTION CountOf( _
Expression AS STRING, _
Find AS STRING _
) AS INTEGER
IF LEN(Find)=0 OR LEN(Expression)=0 THEN
CountOf=0
EXIT FUNCTION
ENDIF
DIM Start AS INTEGER
Start=1
DO WHILE INSTR(Start , Expression , Find) > 0
CountOf=CountOf + 1
Start=1 + INSTR(Start , Expression , Find)
LOOP
END FUNCTION
-
نقل قول: validation کد ملی با RegEx
نقل قول:
نوشته شده توسط
atf1379
نوشته شده توسط mazoolagh https://barnamenevis.org/images/butt...wpost-left.png
شما هر کاری رو که با regex انجام میدین،
با همین توابع string و split و ... هم میشه.
گاهی حتی ساده تر هم هست (پست 44)، و خب گاهی ممکنه خیلی سخت تر باشه - ولی میشه.
به طور مطلق نمبتونین بگین کدوم برتری داره: در سناریو هست که با توجه به شرایط مشخص میشه.
بنده هر کاری کردم نتوانستم مسئله بالا رو از طریق توابع string و split حل کنم . اگر راهنمائی کنن که از طریق توابع فوق به چه صورتی باید برای حل مسئله فوق استفاده کنیم ممنون میشوم
منظورتون مسئله پست 51 هست؟
ساده است که!
تا کجا پیش رفتین؟
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
سلام دوباره
استرینگ ها در اکسس یونیکد نگهداری میشن و توابع استرینگ و regex به زبان حساس نیست.
اونچه برداشت میکنم این هست که شما دنبال تعداد "حالی" هستین، که 4 حرفی هست،
ولی کد پست 34 برای یک استرینگ یک کارآکتری درست کار میکنه - در واقع یک حالت خاص هست.
شما باید اندازه استرینگی رو که دنبالش هستین در محاسبات بیارین:
PUBLIC FUNCTION CountOf( _
Expression AS STRING, _
Find AS STRING _
) AS INTEGER
DIM LenE AS INTEGER, LenF AS INTEGER
LenE=LEN(Expression)
LenF=LEN(Find)
IF LenF=0 OR LenE=0 THEN
CountOf=0
ELSE
CountOf=(LenE - LEN(REPLACE(Expression , Find , "")))/LenF
ENDIF
END FUNCTION
احسنت !:تشویق::تشویق::تشویق:
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
همونطور که در پست 34 اشاره شد از تابع زیر هم برای بدست اوردن تعداد مقدار مورد جستجو میشه استفاده کرد :
Public Function RegExCountWords(ByVal Text As String, PatternText As String) As Long
Dim regx
Set regx = CreateObject("VBScript.RegExp")
regx.Pattern = PatternText
regx.Global = True
RegExCountWords = regx.Execute(Text).Count
End Function
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
برای اینکه متوجه بشیم مطالب آموزشی تا اینجا برای دوستان علاقمند مفید فایده بوده در این پست سوالی ساده طرح می کنیم
با توجه به توضیحات پست 49 میخواهیم یک پترن بنویسیم که در متن انگلیسی زیر کلماتی که حرف آخرشون e میباشه بجای حرف e آخر کلمه عدد 9 جایگزین بشه . مثل کلمه home به hom9 تبدیل بشه.
تاکید می کنم این جایگزینی فقط باید در کلماتی که حرف آخرشون e میباشه صورت بگیره نه کلماتی که حرف e در اول یا وسطشون می باشه
برای تست از کدهای پست 49 استفاده کنین!
Social media star Peanut the Squirrel has been euthanized after being seize from NY home
قطعاً جواب این سوال برای دوستانی که مطالب ارائه شده رو با دقت مرور کرده ان بسیار ساده خواهد بود .
متن خروجی باید بصورت زیر باشه :
Social media star Peanut th9 Squirrel has been euthanized after being seiz9 from NY hom9
Option Compare Database
Option Explicit
Const Expression = "Eager elephants delighted in the serene evening, " + vbCrLf + _
"feeling the gentle breeze under the green trees where they could see the sea." + vbCrLf + _
"e E e se(25) agree- free8 THE e 87e e see. glee_ drive."
Function Replace_RegEx() As String
With New RegExp
.pattern = "e\b"
.Global = True
.IgnoreCase = False
.Multiline = True
Replace_RegEx = .Replace(Expression, "9")
End With
End Function
تست:
? replace_regex
Eager elephants delighted in th9 seren9 evening,
feeling th9 gentl9 breez9 under th9 green trees wher9 they could se9 th9 sea.
9 E 9 s9(25) agre9- free8 THE 9 879 9 se9. glee_ driv9.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
برای اینکه متوجه بشیم مطالب آموزشی تا اینجا برای دوستان علاقمند مفید فایده بوده در این پست سوالی ساده طرح می کنیم
با توجه به توضیحات پست 49 میخواهیم یک پترن بنویسیم که در متن انگلیسی زیر کلماتی که حرف آخرشون e میباشه بجای حرف e آخر کلمه عدد 9 جایگزین بشه . مثل کلمه home به hom9 تبدیل بشه.
تاکید می کنم این جایگزینی فقط باید در کلماتی که حرف آخرشون e میباشه صورت بگیره نه کلماتی که حرف e در اول یا وسطشون می باشه
برای تست از کدهای پست 49 استفاده کنین!
Social media star Peanut the Squirrel has been euthanized after being seize from NY home
قطعاً جواب این سوال برای دوستانی که مطالب ارائه شده رو با دقت مرور کرده ان بسیار ساده خواهد بود .
متن خروجی باید بصورت زیر باشه :
Social media star Peanut th9 Squirrel has been euthanized after being seiz9 from NY hom9
بدون استفاده از regex
Function Replace_Simple() As String
Dim x As String
x = Expression
Dim start As Integer
start = InStr(1, x, "e", vbBinaryCompare)
Do While start > 0
If Not Mid(x, start + 1, 1) Like "[A-Za-z0-9_]" Then
Mid(x, start, 1) = "9"
End If
start = InStr(1 + start, x, "e", vbBinaryCompare)
Loop
Replace_Simple = x
End Function
تست:
? replace_simple
Eager elephants delighted in th9 seren9 evening,
feeling th9 gentl9 breez9 under th9 green trees wher9 they could se9 th9 sea.
9 E 9 s9(25) agre9- free8 THE 9 879 9 se9. glee_ driv9.
اطمینان از این که هر دو روش پاسخ یکسان دارن:
Debug.Print StrComp(Replace_RegEx, Replace_Simple, vbBinaryCompare) = 0
که true هست.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
بدون استفاده از regex
Function Replace_Simple() As String
Dim x As String
x = Expression
Dim start As Integer
start = InStr(1, x, "e", vbBinaryCompare)
Do While start > 0
If Not Mid(x, start + 1, 1) Like "[A-Za-z0-9_]" Then
Mid(x, start, 1) = "9"
End If
start = InStr(1 + start, x, "e", vbBinaryCompare)
Loop
Replace_Simple = x
End Function
تست:
? replace_simple
Eager elephants delighted in th9 seren9 evening,
feeling th9 gentl9 breez9 under th9 green trees wher9 they could se9 th9 sea.
9 E 9 s9(25) agre9- free8 THE 9 879 9 se9. glee_ driv9.
اطمینان از این که هر دو روش پاسخ یکسان دارن:
Debug.Print StrComp(Replace_RegEx, Replace_Simple, vbBinaryCompare) = 0
که true هست.
عالی مثل همیشه!:تشویق::تشویق::تشویق:
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
atf1379
بنده هر کاری کردم نتوانستم مسئله بالا رو از طریق توابع string و split حل کنم . اگر استاد راهنمائی کنن که از طریق توابع فوق به چه صورتی باید برای حل مسئله فوق استفاده کنیم ممنون میشوم
نقل قول:
نوشته شده توسط
mazoolagh
بدون استفاده از regex
Function Replace_Simple() As String
Dim x As String
x = Expression
Dim start As Integer
start = InStr(1, x, "e", vbBinaryCompare)
Do While start > 0
If Not Mid(x, start + 1, 1) Like "[A-Za-z0-9_]" Then
Mid(x, start, 1) = "9"
End If
start = InStr(1 + start, x, "e", vbBinaryCompare)
Loop
Replace_Simple = x
End Function
تست:
? replace_simple
Eager elephants delighted in th9 seren9 evening,
feeling th9 gentl9 breez9 under th9 green trees wher9 they could se9 th9 sea.
9 E 9 s9(25) agre9- free8 THE 9 879 9 se9. glee_ driv9.
اطمینان از این که هر دو روش پاسخ یکسان دارن:
Debug.Print StrComp(Replace_RegEx, Replace_Simple, vbBinaryCompare) = 0
که true هست.
ممنون استاد
لطف کردین
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
atf1379
ممنون
لطف کردین
پترن پست شماره 63 در واقع همون پترن پیشنهادی شما در پست شماره 57 هست
که [] حذف شده - چون فقط یک کارآکتر بررسی میشه بهش نیازی نیست.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
با اجازه جناب بهرامی،
اگر بخواهیم ببینیم چه واژه هایی در یک عبارت تکرار شدن چه پترنی باید استفاده کنیم؟
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
با اجازه جناب بهرامی،
اگر بخواهیم ببینیم چه واژه هایی در یک عبارت تکرار شدن چه پترنی باید استفاده کنیم؟
عرض سلام و ارادت خدمت استاد مازولاق عزیز !
اختیار دارین بزرگوار !
قطعا حضور جنابعالی همراه با طرح سوالات و ارائه نکات فنی و تخصص هم باعث پربار شدن این تاپیک آموزشی میشه وهم دلگرمی بنده برای ادامه فعالیت
-
2 ضمیمه
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
در فرم تشریح و تفسیر عبارات با قاعده فایل آپدیت شده ضمیمه رکوردی با عنوان انواع پترن های کاربردی ایجاد کرده ام که در قسمت سابفرم این رکورد تعداد 112 عبارات Regex که ممکنه در شرایط مختلف به اونها نیاز داشته باشیم اضافه نموده ام . برای دسترسی به پترن های فوق کلمه All رو از کمبوباکس جستجو انتخاب نمائین!
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
در فرم تشریح و تفسیر عبارات با قاعده فایل آپدیت شده ضمیمه رکوردی با عنوان انواع پترن های کاربردی ایجاد کرده ام که در قسمت سابفرم این رکورد تعداد 112 عبارات Regex که ممکنه در شرایط مختلف به اونها نیاز داشته باشیم اضافه نموده ام . برای دسترسی به پترن های فوق کلمه All رو از کمبوباکس جستجو انتخاب نمائین!
بسیار هم عالی!
شایسته است که این تاپیک sticky بشه!
===========
در تصویر اینجور بنظر میاد که رکورد تکراری هم هست، شایدم اشتباه میکنم.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
در فرم تشریح و تفسیر عبارات با قاعده فایل آپدیت شده ضمیمه رکوردی با عنوان انواع پترن های کاربردی ایجاد کرده ام که در قسمت سابفرم این رکورد تعداد 112 عبارات Regex که ممکنه در شرایط مختلف به اونها نیاز داشته باشیم اضافه نموده ام . برای دسترسی به پترن های فوق کلمه All رو از کمبوباکس جستجو انتخاب نمائین!
در مورد تشخیص حروف فارسی:
فکر کنم بهتره یک تاپیک جدا واسش بزنین،
و این پترن که در تصویر هست احتمالا نیاز به تکمیل داشته باشه.
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
اگر بخواهیم ببینیم چه واژه هایی در یک عبارت تکرار شدن چه پترنی باید استفاده کنیم؟
ظاهراً دوستان علاقه چندانی به موضوع این تاپیک ندارند .
با توجه به اینکه یجورائی پترن مورد نظر جنابعالی رو به فایل آپدیت شده در پست 70 اضافه نموده ام ولی ...
بعد از این همه مدت که از زمان ایجاد این تاپیک میگذره از دوستان انتظار میرفت که در خصوص مطالب آموزشی اظهار نظری هرچند مختصر ارائه نماین ولی متاسفانه به استثناء یک نفر بقیه دوستان صرفاً نظاره گر مطالب هستن
-
نقل قول: استفاده از Regular Expressions یا به اخصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
ظاهراً دوستان علاقه چندانی به موضوع این تاپیک ندارند ... صرفاً نظاره گر مطالب هستن
این regex بسیار بدقلق هست و شیب منحنی یادگیری اش هم کمه!
گذشته از این: بیشتر و نزدیک به همه، فقط برای رفع مشکلی که همون لحظه دچارش هستن اینجا میان و نه برای یاد گرفتن.
ولی در طی زمان بازدیدکننده ها با جستجو اینجا رو پیدا و ازش استفاده میکنن، پس دلسرد نباشین و ادامه بدین - تو نیکی میکن و در دجله انداز!
نقل قول:
نوشته شده توسط
eb_1345
... پترن مورد نظر (پست شماره 68) رو به فایل آپدیت شده در پست 70 اضافه نموده ام ...
آره، در تصویر هم دیده میشه - ولی اون پترن (در همه حالتها) درست نیست !
باید سر فرصت با مثال نشون بدم.
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
mazoolagh
آره، در تصویر هم دیده میشه - ولی اون پترن (در همه حالتها) درست نیست !
من چند مورد رو امتحان کردم واژه های تکراری رو نمایش میده ولی بعضی از اونها سلکت نمیشن
البته فکر کنم بشه که با همین پترن اول موارد تکراری ( همون هائی که سلکت میشن) پشت سر هم بصورت یک رشته تبدیل کرد و بعد موارد تکراری این رشته رو حذف کرد . که در نهایت در رشته واژه هائی که تکرار شده اند بدست بیاد.
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
نقل قول:
نوشته شده توسط
eb_1345
البته فکر کنم بشه که با همین پترن اول موارد تکراری ( همون هائی که سلکت میشن) پشت سر هم بصورت یک رشته تبدیل کرد و بعد موارد تکراری این رشته رو حذف کرد . که در نهایت در رشته واژه هائی که تکرار شده اند بدست بیاد.
لطفاً توابع پائین رو تست بفرمائین !
Public Function RemoveDupesInString(strText As String, Optional strDelim As String = " ") As String
Dim varArray As Variant
Dim intI As Integer
Dim strOut As String
strText = " " & strText & " "
varArray = Split(strText, strDelim)
For intI = 0 To UBound(varArray) - 1
If InStr(strOut, varArray(intI)) = 0 Then
strOut = strOut & varArray(intI) & " "
End If
Next
RemoveDupesInString = Trim(strOut)
End Function
Public Function DupesRegexp(StrReg As String)
Dim regx
Dim Matches As Object
Dim Match As Object
Dim Str As String
Set regx = CreateObject("VBScript.RegExp")
regx.Global = True
regx.IgnoreCase = True
regx.Multiline = True
regx.Pattern = "(\b\w+\b)(?=.*\b\1\b)"
Set Matches = regx.Execute(StrReg)
For Each Match In Matches
Str = Str & " " & Match.Value
Next
Str = Right(Str, Len(Str) - 1)
MsgBox RemoveDupesInString(Str)
End Function
Call DupesRegexp("Secure, smart, and easy to use email Get more done with Gmail. Now integrated with google Chat, Google Meet, and more, all in one place.")
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
ایراداتی در کد های فوق وجود داره که نیاز به چکش کاری استاد داره
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
سلام دوباره
الان یه کمی مطلب پیچیده شد - بذارین یکی یکی بریم جلو.
1- این پترن
(\b\w+\b)(?=.*\b\1\b)
دو تکه اس،
بهتره پیش از هر کاری عملکرد تکه اول رو که قراره کلمه ها رو پیدا کنه بررسی کنیم:
Sub duplicate_words()
Const pattern = "(\b\w+\b)"
Dim Parts()
Parts = Array( _
"This is the first part,", _
"and this is the second part,", _
"now and then", _
"now another part added.")
test_it Join(Parts, " "), pattern
test_it Join(Parts, vbCrLf), pattern
End Sub
Sub test_it(Expression As String, pattern As String)
Dim mc As MatchCollection
Dim m As match
With New RegExp
.Global = True
.IgnoreCase = True
.Multiline = True
.pattern = pattern
Set mc = .Execute(Expression)
End With
Debug.Print "pattern=" & pattern, "count=" & mc.Count
For Each m In mc
Debug.Print m & " ";
Next
Debug.Print
End Sub
خروجی:
pattern=(\b\w+\b) count=18
This is the first part and this is the second part now and then now another part added
pattern=(\b\w+\b) count=18
This is the first part and this is the second part now and then now another part added
همینجور که دیده میشه این پترن با نقطه و ویرگول (چیزهای دیگه هست که میتونین خودتون تست کنین)
رفتار مشخصی داره و اون ها رو کنار میذاره -
که اگر در سناریو کاری ما مشکلی نداشته باشه خب همین خوبه و تا اینجا کلمه ها رو درست تشخیص میده (بخش پیدا کردن تکراری رو جدا بررسی میکنیم)،
وگرنه باید یک فکر دیگه برداریم.
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
حالا وضعیت زیر رو بببینیم:
test_it "sin(5x) a+b=c 192.168.1.1 first-name last_name [date] (\b\w+\b) end. ", pattern
نتیجه:
pattern=(\b\w+\b) count=17
sin 5x a b c 192 168 1 1 first name last_name date b w b end
الان دیگه دیده میشه که رفتار پترن چجوری هست،
بنابراین باید هم از ساختار متنی که قرار هست تکراری ها رو در اون پیدا کنیم آگاهی دقیق داشته باشیم،
هم این که تعریف کلمه رو برای خودمون مشخص کنیم.
-
نقل قول: استفاده از Regular Expressions یا به اختصار RegEx برای جستجو و جایگذاری عبارت در متن
در یک سناریوی دقیقتر، کلمه اینجوری تعریف میشه که هر رشته ای از کارآکترها که white space نداشته باشه:
test_it "sin(5x) a+b=c 192.168.1.1 first-name last_name [date] (\b\w+\b) end. ", "(\S+)"
pattern=(\S+) count=8
sin(5x) a+b=c 192.168.1.1 first-name last_name [date] (\b\w+\b) end.
انتخاب پترن به سناریوی ما برمیگرده - اینجور نیست که بگیم یکی بهتر هست،
شاید هیچکدام اینها پاسخگوی نیاز ما نباشه و لازم باشه یک پترن مناسب طراحی کنیم.