Dalam js, ungkapan biasa diwakili oleh objek RegExp RegExp ialah singkatan ungkapan biasa. Corak ringkas RegExp boleh menjadi satu aksara. Corak yang lebih kompleks termasuk lebih banyak aksara dan boleh digunakan untuk penghuraian, semakan format, penggantian, dsb. Anda boleh menggunakan pembina RegExp() untuk mencipta objek RegExp, atau anda boleh menggunakan sintaks literal.
1. Pengenalan kepada RegExp.
RegExp ialah ungkapan biasa (ungkapan biasa, sering disingkatkan sebagai regex, regexp atau RE/re/reg dalam kod), yang menggunakan rentetan tunggal untuk menerangkan dan memadankan satu siri corak carian rentetan yang mematuhi peraturan sintaks tertentu . Mod carian tersedia untuk carian teks dan penggantian teks.
Ungkapan biasa ialah corak carian yang dibentuk oleh jujukan aksara Apabila anda mencari data dalam teks, anda boleh menggunakan corak carian untuk menerangkan kandungan yang ingin anda tanyakan, maksudnya, ungkapan biasa ialah objek yang menerangkan corak aksara , yang boleh digunakan untuk memadankan corak rentetan dan mencari serta menggantikannya.
Ungkapan biasa yang dipanggil boleh difahami secara langsung sebagai ungkapan peraturan atau corak, yang menyatakan peraturan tertentu yang boleh difahami oleh komputer, tetapi merupakan ungkapan teks yang sukar difahami oleh orang biasa semua carian teks dan penggantian teks, secara ringkasnya, adalah untuk memproses rentetan.
2.
(1), charAt() Dapatkan aksara tertentu dan kembalikan aksara tertentu dalam rentetan.
(2), split() Pisahkan rentetan dan dapatkan tatasusunan.
(3), cari()Cari kedudukan di mana watak tertentu mula-mula muncul. Nilai pulangan adalah nilai berangka. -1 dikembalikan.
(4), padankan()Cari aksara yang ditentukan dalam rentetan dan kembalikan aksara tersebut Jika anda tidak menggunakan ungkapan biasa, hanya kejadian pertama aksara yang ditentukan akan dikembalikan dan tiada padanan ke belakang akan dilakukan. Jika anda menggunakan ungkapan biasa dan melakukan pemadanan global, Mengembalikan semua aksara yang ditentukan dalam rentetan dalam bentuk tatasusunan, atau mengembalikan null jika tidak dijumpai.
(5), ganti() Ganti aksara dan kembalikan rentetan baharu. Ia lebih baik digunakan dengan ungkapan biasa dan boleh menggantikan semua padanan.
<script> var str='abcdefgca'; //返回字符串中某一位的字符。 alert(str.charAt()); //返回:d //查找字符串首次出现的位置。 alert(str.search('z')); //返回:- //查找指定的字符。 //只返回第一次出现的c,不再向后匹配。 alert(str.match('c')); //返回:c //将'a'替换为'i'。 //只替换了第一个位置的a,不再向后匹配。 alert(str.replace('a', 'i')); //返回:ibcdefgca //分割字符串。 var str='--aaa--cd'; var arr=str.split('-'); //返回:,,aaa,,cd alert(arr); </script>
Contoh: Gunakan kaedah biasa untuk mencari semua nombor dalam rentetan
Idea pelaksanaan: Tidak sukar untuk mencari nombor dalam rentetan Gunakan penghakiman untuk mengekstrak nombor dalam rentetan dahulu. Kemudian mesti ada lebih daripada satu nombor dalam rentetan, jadi rentetan kosong diperlukan untuk menyimpannya . Ekstrak aksara angka, kemudian tambahkan aksara angka ini pada tatasusunan, dan akhirnya kembali, dan anda selesai. Mari lihat bagaimana program ini dilaksanakan:
<script> var str=' abc d aa c zz -=-=s-'; var arr=[]; var num=''; //首先循环遍历字符串 for(var i=;i<str.length;i++){ //再判断当前字符大于等于并且小于等于,则为数字 if(str.charAt(i)>='' && str.charAt(i)<=''){ //那么就将当前的字符存储在空字符串中 num += str.charAt(i); } else{ //如果字符串中有值。 if(num){ //将值添加到数组中。 arr.push(num); //再清空字符串,避免重复添加。 num=''; } } } //最后在整个字符串结束之后有可能还会有数字,再做一次判断。 if(num){ //如果还有值就添加到数组中。 arr.push(num); //再清空字符串。 num=''; } //返回:OK,现在返回就完成了。 alert(arr); //返回:,,,,,,, </script>
Walaupun ia boleh diselesaikan menggunakan kaedah biasa dan mempunyai struktur yang jelas, kodnya agak panjang Jika anda menggunakan ungkapan biasa, maka satu ungkapan boleh menyelesaikan begitu banyak kerja, yang sangat mudah menggunakan ungkapan biasa.
3. Gunakan peraturan biasa.
Sintaks ungkapan biasa: var re = new RegExp('pattern', 'modifier');
Corak ialah corak ungkapan dan pengubah suai digunakan untuk menentukan padanan global, ketidakpekaan huruf besar-besaran, dsb. Bentuk lengkap ialah ungkapan biasa.
Melihat sintaks biasa kelihatan seperti ini, bukankah ini sintaks biasa untuk objek yang baru dibuat dalam JS, ini bermakna mencipta objek biasa yang baharu? Kita semua tahu bahawa kita harus cuba mengelak daripada menggunakan kata kunci baharu sudah pasti akan mencipta objek baharu, yang juga bermakna ia menduduki sejumlah ruang memori Jika tidak dikendalikan dengan betul, pengumpulan yang berlebihan akan menyebabkan limpahan memori sumber yang agak mahal, yang tidak sesuai untuk pelaksanaan pengoptimuman kod. Pada masa yang sama, cara penulisan ini tidak menggambarkan kuasa keteraturan Ia sepatutnya sangat ringkas Oleh itu, dalam penggunaan sebenar, sintaks biasa gaya JS ini tidak digunakan, seperti berikut :
Sintaks: var re = /mode/modifier;
Gaya ini agak ringkas dan merupakan cara ekspresi yang tidak dapat difahami oleh orang biasa.
(1), pengubah suai.
Pengubah suai digunakan untuk melakukan pemadanan global dan kepekaan huruf besar.
Abaikan huruf besar: i (singkatan daripada abaikan, terjemahan bahasa Cina ialah: abaikan)
Padanan global: g (singkatan daripada global, terjemahan bahasa Cina: semua/global)
Contoh: Carian global untuk aksara tertentu
<script> var str='AbCdEFgiX'; //JS风格: //这个正则表达式什么也不代表,只代表abc本身。 var reg=new RegExp('abc', 'i'); alert(str.match(reg)); //返回:AbC //常用风格: var re=/efg/i; alert(str.match(re)); //返回:EFg </script>
4. Tanda kurung dan aksara meta.
(1), kurungan segi empat sama.
Tanda kurung segi empat sama digunakan untuk mencari aksara dalam julat tertentu.
①、Mana-mana watak
Ungkapan: [abc]
Cari sebarang aksara dalam kurungan segi empat sama.
[] di sini bermaksud atau, iaitu, mana-mana yang muncul akan dilakukan.
<script> var str='apc xpc ppc bpc spc opc'; //[apx]pc,随便出现哪个都行,即:apc ppc xpc var re=/[apx]pc/g; alert(str.match(re)); //返回前个pc。 </script>
②、范围查找。
表达式:[0-9] [a-z] [A-z] [A-Z]
[0-9] 查找任意 0 - 9 的数字。
[a-z] 查找任意 a - z 的字符。
[A-z] 查找任意 大写A - 小写z 的字符。
[A-Z] 查找任意 大写A - 大写Z的字符。
③、排除查找。
表达式:[^abc] [^a-z] [^0-9]
[^abc] 查找任意不在方括号中的字符。
[^a-z] 查找任意除了字母以外的字符,包括数字符号中文外文。
[^0-9] 查找任意除了数字以外的字符,包括字母符号中文外文。
<script> var str='ot out o.t o t o`t ot ot'; //o和t中间除了数字,什么都可以 var re=/o[^-]t/g; alert(str.match(re)); //返回:out,o.t,o t,o`t </script>
④ Pilih carian.
Ungkapan: (a|b|c)
Cari mana-mana pilihan yang ditentukan, a atau b atau c.
⑤ Padanan juga boleh menggunakan mod gabungan, seperti: [a-z0-9A-Z] [^a-z0-9]
.[a-z0-9A-Z] Sebarang huruf besar atau huruf kecil dan nombor.
[^a-z0-9] Apa-apa sahaja kecuali huruf dan nombor boleh diterima.
(2) Metakarakter.
Metacharacter ialah watak dengan makna istimewa dan juga boleh dipanggil watak melarikan diri.
Berikut ialah beberapa aksara meta yang biasa digunakan:
Metacharacter | Penerangan | Gunakan |
. | Mencari satu aksara, mewakili mana-mana aksara, tidak termasuk baris baharu dan penamat baris. | Ia tidak digalakkan untuk digunakan, ia terdedah kepada masalah. |
w | Cari aksara perkataan, termasuk nombor dan garis bawah bahasa Inggeris, bersamaan dengan [a-z0-9] | /w/ |
W | Cari aksara bukan perkataan, bersamaan dengan [^a-z0-9] | /W/ |
d | Cari nombor, bersamaan dengan [0-9] | /d/ |
D | Cari bukan digit, bersamaan dengan [^0-9] | /D/ |
s | Cari aksara ruang kosong, termasuk ruang, pemulangan pengangkutan, tab, suapan baris dan suapan borang tidak boleh dipaparkan. | /s/ |
S | Cari aksara bukan ruang putih. | /S/ |
b | Mencari padanan pada permulaan atau akhir perkataan, atau mengembalikan batal jika tiada padanan ditemui. | /b/ |
B |
Cari padanan yang bukan sempadan perkataan, iaitu, ia bukan pada permulaan atau akhir Jenis aksara sebelumnya dan seterusnya dalam kedudukan sepadan adalah sama: iaitu, kedua-duanya mestilah perkataan , atau mesti kedua-duanya bukan perkataan, pada permulaan dan akhir rentetan dianggap sebagai aksara bukan perkataan, jika tidak dipadankan, null dikembalikan. |
/B/ |
n | Mencari aksara baris baharu dan mengembalikan kedudukan itu jika ditemui, atau -1 jika tidak ditemui. | /n/ |
f | Cari pemisah halaman. | /f/ |
r | Cari watak pemulangan kereta. | /r/ |
t | Cari aksara tab. |
5.
Pengkuantiti yang dipanggil ialah pengkuantiti, iaitu nombor Ia digunakan dalam ungkapan biasa untuk menyatakan bilangan kejadian.
Berikut ialah beberapa pengkuantiti yang biasa digunakan:
Pengkuantiti | Penerangan | Gunakan |
* | sifar atau beberapa kali, bersamaan dengan {0,} | Tidak disyorkan, julatnya terlalu luas dan tidak cukup tepat. |
? | sifar atau satu kali, bersamaan dengan {0, 1} | /10?/g Melakukan carian global untuk 1, termasuk sifar atau 1 '0' serta-merta mengikutinya. |
sekali atau beberapa kali, bersamaan dengan {1, } | /w /g Lakukan carian global untuk sekurang-kurangnya satu perkataan. | |
{n} | Tepat n kali | /d{4}/g melakukan carian global untuk nombor empat digit. |
{n,} | Sekurang-kurangnya n kali, tiada had paling banyak | /d{3,}/g Melakukan carian global untuk nombor yang mengandungi sekurang-kurangnya tiga digit. |
{n, m} | Sekurang-kurangnya n kali, paling banyak m kali | /d{3,4}/g Lakukan carian global untuk nombor yang mengandungi tiga atau empat digit. |
Berikut ialah beberapa corak padanan yang biasa digunakan:
Mod | Penerangan | Gunakan |
^a | Mana-mana watak yang bermula dengan bermakna permulaan baris | /^d/ Bermula dengan nombor /^a/g Carian global untuk aksara bermula dengan 'a' |
a$ | Mana-mana watak yang berakhir dengan a, menunjukkan penghujung baris | /d$/ Berakhir dengan nombor /z$/g Carian global untuk aksara yang berakhir dengan 'z' |
?=a | Mana-mana watak diikuti dengan | /a(?= b)/g Carian global untuk 'a' diikuti dengan aksara 'b' |
?!a | Mana-mana watak yang tidak diikuti oleh | /c(?= d)/g Carian global untuk aksara yang tidak mengikut 'd' selepas 'c' |
6、字符串和正则配合。
(1)、search()配合正则
实例:找出字符串中第一次出现数字的位置
<script> var str='asdf zxcvbnm'; //元字符d,表示转义为数字 var re=/\d/; alert(str.search(re)); //返回: 第一个数字为出现在第位 </script>
(2)、match()配合正则
其实没有什么东西是非正则不可的,只是正则可以让做东西更方便。下面就完成本章遗留的历史问题,怎么使用正则,能一句代码就完成普通方法需要很多行代码才能完成的东西。
在实例之前,先看看match()与正则的配合。
<script> var str='asdf zxcvm'; //找出字符串中的数字可以使用元字符\d var re=/\d/; //没告诉系统要找多少数字,系统在找到数字后就返回 alert(str.match(re)); //返回: //因此需要全局匹配,使用修饰符g var re=/\d/g; //没告诉系统要找几位,系统会将所有找到的数字返回 alert(str.match(re)); //返回:,,,,,,,,,,,, //所以可以使用两个元字符,告诉系统要找的数字是位 var re=/\d\d/g; //显然这样是不可取的,因为数字的位数并不固定,可能是位,有可能还是多位 alert(str.match(re)); //返回:,,,, //所以需要用到量词+,+代表若干,也就是多少都可以。 var re=/\d+/g; //现在返回正确。 alert(str.match(re)); //返回:,,,, </script>
实例:使用正则找出字符串中所有数字
<script> var str=' abc d aa c zz -=-=s-'; //alert(str.match(/\d+/g)); //元字符d也可以使用[-]代替,到随便哪个都行。 alert(str.match(/[-]+/g)); //返回:,,,,,,, </script>
正则是强大的字符串匹配工具,就这样简单的使用一句代码就完成了。
(3)、replace()配合正则
<script> var str='abc zaaz deaxcaa'; //将字符串中的a替换为数字 alert(str.replace('a', )); //仅仅只将第一个a替换为 //配合正则使用匹配所有a再替换 var re=/a/g; alert(str.replace(re, '')); //返回所有的a都为 </script>
实例:简单的敏感词过滤
所谓的敏感词,就是法律不允许的词语,一切非法词都可以叫做敏感词,这包括的范围就太广了,比如危害国家安全,反对宪法确立的基本原则,散步谣言,扰乱民心,扰乱社会秩序,破坏社会稳定,色情、暴力、赌博、虚假、侵害、骚扰、粗俗、猥亵或其他道德上令人反感的词,以及含有法律规定或禁止的其他内容的词语。在平时最常见也是大多数人都会用的词莫属道德上令人反感的词了,说斯文一点就是吵架时用于攻击别人的词语。这里就列举几个热门的网络词语作为例子。
<!DOCTYPE html> <html> <head> <meta charset="UTF-"> <title>JavaScript实例</title> <script> window.onload=function (){ var oBtn=document.getElementById('btn'); var oTxt=document.getElementById('txt'); var oTxt=document.getElementById('txt'); oBtn.onclick=function (){ //这里的|在正则中表示 或 的意思 var re=/元芳|萌萌哒|然并卵|毛线|二货|城会玩/g; //文本框的值等于文本框的值过滤掉敏感词 oTxt.value=oTxt.value.replace(re,'***'); }; }; </script> </head> <body> <textarea id="txt" rows="" cols=""></textarea><br> <input id="btn" type="button" value="过滤"><br> <textarea id="txt" rows="" cols=""></textarea> </body> </html>
可在第一个文本框中输入一些相关语句,点击过滤按钮,查看过滤后的效果。
此外,支持正则表达式的 String 对象的方法还包括 split() 方法,可把字符串分割为字符串数组。
7、RegExp对象方法。
在JS中,RegExp对象是一个预定义了属性和方法的正则表达式对象。
(1)、test()
test() 方法用于检测一个字符串是否匹配某个模式,也就是检测指定字符串是否含有某个子串,如果字符串中含有匹配的文本,返回 true,否则返回 false。
语法:RegExpObject.test(str)
调用 RegExp 对象 re 的 test() 方法,并为它传递字符串str,与这个表示式是等价的:(re.exec(str) != null)。
实例:搜索字符串是否含有指定的字符
<script> var str='The best things in life are free, like hugs, smiles, friends, kisses, family, love and good memories.'; var re=/i/; alert(re.test(str)); //返回:true var reg=/z/; alert(reg.test(str)); //返回:false //上面的代码可以不用定义正则的变量,直接使用,将两行合并为一行。 alert(/i/.test(str)); alert(/z/.test(str)); </script>
(2)、exec()
exec() 方法用于检索字符串中的正则表达式的匹配,提取指定字符串中符合要求的子串,该方法返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回 null。可以使用循环提取所有或者指定index的数据。
语法:RegExpObject.exec(str)
exec() 方法的功能非常强大,它是一个通用的方法,可以说是test() 方法的升级版,因为他不仅可以检测,而且检测到了可以直接提取结果。该方法使用起来比 test() 方法以及支持正则表达式的 String 对象的方法更为复杂。
<script> var str = 'good good study day day up'; var re = /good/; var arr = re.exec(str); console.log(arr); //控制台显示:["good"]点开后显示: "good",index ,input "good good study day day up"。 console.log(arr.index); //控制台显示: console.log(arr.input); //控制台显示:good good study day day up </script>
通过上面的实例,可以看到,如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。此数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。
除了数组元素和 length 属性之外,exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。我们可以看出,在调用非全局的 RegExp 对象的 exec() 方法时,返回的数组与调用方法 String.match() 返回的数组是相同的。
什么是"与子表达式相匹配的文本"?
所谓的子表达式就是正则表达式中包含在圆括号中的内容。看下面实例:
<script> var str = 'good good study day day up'; var re = /g(o+)d/; var arr = re.exec(str); console.log(arr); //显示:["good", "oo"]点开后显示: "good", "oo", index ,input: "good good study day day up" console.log(arr.length); //显示: var reg = /(o+)/; //var reg = /o+/; 只返回一个"oo",长度为 var arr = reg.exec(str); console.log(arr); //显示:["oo", "oo"]点开后显示: "oo", "oo", index ,input: "good good study day day up" console.log(arr.length); //显示: </script>
通过上例,可以看到,子表达式是一个大的表达式的一部分,并且必须用()包含起来。一个表达式可使用多个子表达式,同时还支持多层嵌套,把一个表达式划分为多个子表达式的目的是为了把那些子表达式当作一个独立的元素来使用。也就是说表达式中的子表达式可以作为整个表达式返回,也可以作为一个单独的表达式返回。所以上面的数组长度为 2。
使用子表达式是为了提取匹配的子字符串,表达式中有几个()就有几个相应的匹配字符串,顺序会依照()出现的顺序依次进行,并且()中可以使用 或"|" 进行多个选择。也就是说可以使用()对字符进行分组,并保存匹配的文本。
如果该方法使用全局匹配,则找到第一个指定字符,并存储其位置,如果再次运行 exec(),则从存储的位置(lastIndex)开始检索,并找到下一个指定字符,存储其位置。lastIndex属性是RegExp对象属性,是一个整数,标示开始下一次匹配的字符位置。看下面实例:
<script> var str = 'good good study day day up'; var re = /good/g; var arr; do{ arr = re.exec(str); console.log(arr); console.log(re.lastIndex); } while(arr !== null) /* 结果如下: 显示:["good"],点开后: "good", index , input "good good study day day up"。 lastIndex为。 显示:["good"],点开后: "good", index , input "good good study day day up"。 lastIndex为。 显示:null lastIndex为。 */ </script>
在调用非全局的 RegExp 对象的 exec() 方法时,返回的数组与调用 String.match() 返回的数组是相同的。但是,当 RegExpObject 是一个全局正则表达式时,exec() 的行为就稍微复杂一些。它会在 RegExpObject 的 lastIndex 属性指定的字符处开始检索字符串 string。当 exec() 找到了与表达式相匹配的文本时,在匹配后,它将把 RegExpObject 的 lastIndex 属性设置为匹配文本的最后一个字符的下一个位置。这就是说,可以通过反复调用 exec() 方法来遍历字符串中的所有匹配文本。当 exec() 再也找不到匹配的文本时,它将返回 null,并把 lastIndex 属性重置为 0。
通过上面实例,可以看到,当第三次循环时,找不到指定的 "good",于是返回null,lastIndex值也变成0了。找到的第一个"good"的lastIndex值为4,是匹配文本最后一个字符的下一个位置。
<script> var str = 'good good study day day up'; var re = /good/g; var arr; while((arr = re.exec(str)) != null){ console.log(arr); console.log(re.lastIndex); } /* 结果如下: 显示:["good"],点开后: "good", index , input "good good study day day up"。 lastIndex为。 显示:["good"],点开后: "good", index , input "good good study day day up"。 lastIndex为。 */ </script>
这里需要注意,如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串(仍然使用旧的re),就必须手动地把 lastIndex 属性重置为 0。
无论 RegExpObject 是否是全局模式,exec() 都会把完整的细节添加到它返回的数组中。这就是 exec() 与 String.match() 的不同之处,后者在全局模式下返回的信息要少得多。因此可以这么认为,在循环中反复地调用 exec() 方法是唯一一种获得全局模式的完整模式匹配信息的方法。
(3)、compile
compile() 方法用于在脚本执行过程中编译正则表达式,也可用于改变和重新编译正则表达式。主要作用是改变当前(re)匹配模式。
语法:RegExpObject.compile(模式, 修饰符)
模式就是正则表达式,修饰符用于规定匹配的类型,g匹配全局,i忽略大小写,gi全局匹配忽略大小写。
该方法是改变匹配模式时使用的,一般情况下,能用到的地方很少。
实例:在全局中忽略大小写 搜索"day",并用 "天" 替换,然后通过compile()方法,改变正则表达式,用 "日" 替换 "Today" 或 "day"。
<script> var str = 'Today is a beautiful day, Day day happy!'; var re = /day/gi; var str = str.replace(re, '天'); console.log(str); //输出:To天 is a beautiful 天, 天 天 happy! reg = /(to)?day/gi; reg.compile(reg); str = str.replace(reg, '日'); console.log(str); //输出:日 is a beautiful 日, 日 日 happy! </script>
8.
Ungkapan biasa juga dipanggil ungkapan biasa, jadi apabila menulis, prosesnya sama seperti menulis JS, fikir dahulu dan kemudian tulis. Perkara yang paling penting ialah memahami peraturan yang dia ingin nyatakan Pertama, teliti penampilannya untuk melihat rupanya, iaitu, dalam format apa ia wujud. Kemudian tulis ungkapan mengikut format ini untuk melihat sama ada ia boleh. Capai tujuan kami yang dijangkakan, sebenarnya, secara amnya menggambarkan format secara langsung sebagai ungkapan tidak akan mencapai kesan yang diharapkan , anda hanya boleh membuat sedikit pengubahsuaian berdasarkan rangka kerja ini, dan akhirnya ia akan menjadi ungkapan yang sempurna. Sebagai contoh, jika anda ingin menulis ungkapan biasa untuk mengesahkan nombor telefon mudah alih, semua orang tahu bahawa nombor telefon bimbit ialah 11 digit, semua nombor, dan permulaannya ialah 1, diikuti dengan 2 digit, kerana operator yang berbeza, boleh menjadi banyak kombinasi, diikuti dengan 8 Digit ialah sebarang nombor, jadi kita boleh menetapkan bahawa permulaan mestilah 1, 2 digit seterusnya dihadkan mengikut kombinasi berbeza yang disediakan oleh setiap operator, dan akhirnya masukkan 8 digit sebarang nombor. Dengan cara ini, walaupun rangka kerja utama telah siap, terdapat juga keadaan khusus untuk nombor telefon mudah alih , jika tidak, pengguna perlu memasukkan nombor telefon bimbitnya di hadapan, kemudian klik Sebut, dan sistem akan muncul tetingkap yang anda masukkan adalah bulu, dan sistem tidak mengenalinya , jadi anda hanya perlu mengubah suai rangka kerja dan pertimbangkan situasi ini dan anda sudah selesai.
Jadi, nampaknya ungkapan biasa sangat mudah, tetapi sebenarnya ia agak sukar Mengapa anda begitu diao? Dalam analisis terakhir, ungkapan seperti ini yang sukar difahami oleh orang biasa Apabila saya menulisnya, saya tahu dengan tepat apa yang diungkapkannya. t saya mengenalinya? Sebenarnya, ini adalah proses di mana amalan menjadi sempurna. Saya masih ingat ada teks yang mengatakan, "Memori yang baik tidak sebaik pena yang buruk."