顯示具有 程式設計 標籤的文章。 顯示所有文章
顯示具有 程式設計 標籤的文章。 顯示所有文章

2020-04-28

regular expression 的 Lookahead 與 Lookbehind

[regular expression]
這裡不教導簡單的 regular expression, 首先你必需瞭解一些基本的 RE。例如 g 是指全域尋找,[56]是指 5 或 6,[2-8]是指 2 到 8。
基本的 RE 很簡單,到處都有資料,要瞭解沒有任何困難。

【開始】

所謂 regular expression 的 expression 是指表達式,也就是說尋找「符合整個表達式的規則」的資料的意思。
對程式設計師來說落落長的「說明」是沒太大用處的,程式碼才能表達一切。但是上面這句話卻是例外,不領會這句話的意義就代表不懂或一知半解 regular expression 的意思。

0. 基礎說明

在這裡我們將 RE 的格式 (?=c)m 中,c 我們稱其為「條件表達式」或「條件式」,而 m 稱之為「主表達式」
各種格式例如以下:
(?=c)m、m(?=c)、(?<=c)m、m(?<=c)

Lookahead符合條件時從前面開始抓資料。當條件式在主表達式「前面」時則取值判斷時包含該條件式,在後面時則看取多少「長度」。
Lookbehind符合條件時從後面開始抓資料。 當條件式在主表達式「後面」時則取值判斷時包含該條件式,在後面時則看取多少「長度」。
positive: 要符合條件式,「必需」符合條件式
negative: 要不符合條件式, 「不可」符合條件式(限制不能同條件式所述)
front: 條件式在主表達式「前面」的這種 expression
behind: 條件式在主表達式「後面」的這種 expression

RE 條件比對順序:RE 條件比對順序為由左至右比對,所以前後順序很重要

1. lookahead 及 lookbehind

   很多人跟你說 lookahead 就是往前看,所以格式 m(?=c) 就是找 m 後面有 c 的資料。
   誰跟你說的?
   包含外國人都跟你說 m followed by c, 其實這是大大的誤解了。
   難道我不能這樣找 (?=c)m ,意指找 c 在 m 前的「符合這個表達式規則」的資料? 這時後難道要叫「往後看」?lookbehind?
   很顯然的並不是這樣的,因為 lookbehind 在 RE 裡是另一個意思。
   RE 最重要的是「表達式順序」,
   lookahead 意指若條件式(c)在前面時,則取值判斷時要包含 c 值,但條件式若在後面時取值判斷時則不包含 c值。即符合條件時從前面開始抓資料。相反的,
   lookbehind 意指若條件式(c)在前面時,則取值判斷時不包含 c 值,但條件式若在後面時取值判斷時則要包含 c值。即符合條件時從後面開始抓資料。

2. 用例子證明一切

所以到這裡我們總共有 lookahead/lookbehind, positive/negative, condition position front/behind 共 2 x 2 x 2 = 8 種狀況,
再加上我們再用長度 1 及 2 讓觀念更清楚,於是共有 8 x 2 = 16 種狀況
# Lookahead
## positive Lookahead (positive ?=)
### positive Lookahead, 1 char, condition in front
"01234567890".match(/(?=[5])[2-8]/g)
結果: ["5"]
分析: 因為 lookahead 在 front 時取值判斷要包含其值,又我們只要1個字元,故直接只有 5 符合其值,毫無懸念。
### positive behind, 1 char, condition in behind
"01234567890".match(/[2-8](?=[5])/g)
結果: ["4"]
分析: 因為 lookahead 在 behind 時取值判斷"不"包含其值,又我們只要1個字元,因 4 的下1位5符合,取值不取5,故答案為 4
### positive Lookahead, 2 chars, condition in front
"01234567890".match(/(?=[5])[2-8]{2}/g)
結果: ["56"]
分析: 因為 lookahead 在 front 時取值判斷要包含其值,取2個字元,故直接只有 [5]6 符合其值
### positive behind, 2 chars, condition in behind
"01234567890".match(/[2-8]{2}(?=[5])/g)
結果: ["34"]
分析: 因為 lookahead 在 behind 時取值判斷"不"包含其值,取2個字元,故答案為 34[5]
## negative lookahead (negative ?!)
### negative lookahead, 2 chars, condition in front
"01234567890".match(/(?![6])[2-8]{2}/g)
結果: ["23", "45", "78"]
### negative lookahead, 2 chars, condition in behind
"01234567890".match(/[2-8]{2}(?![6])/g)
結果: ["23", "56", "78"]
## negative 1
### negative lookahead, 1 char, condition in front
"01234567890".match(/(?![5])[2-8]/g)
結果: ["2", "3", "4", "6", "7", "8"]
### negative lookahead, 1 chars, condition in behind
"01234567890".match(/[2-8](?![5])/g)
結果: ["2", "3", "5", "6", "7", "8"]


# Lookbehind
## positive
### positive 2 front
"01234567890".match(/(?<=[5])[2-8]{2}/g)
結果: ["67"]
分析: 因為 Lookbehind 在 front 時取值判斷"不"包含其值,取2個字元,5為前置不取,[5]67,故答案為 67
### positive 2 behind
"01234567890".match(/[2-8]{2}(?<=[5])/g)
結果: ["45"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,取2個字元,故答案為 4[5] (含5)
### positive 1 front
"01234567890".match(/(?<=[5])[2-8]/g)
結果: ["6"]
### positive 1 behind
"01234567890".match(/[2-8](?<=[5])/g)
結果: ["5"]
## negative
### negative 2 front
"01234567890".match(/(?<![5])[2-8]{2}/g)
結果: ["23", "45", "78"]
分析: 因為 Lookbehind 在 front 時取值判斷不包含其值,這裡取2個字元,故第1組23,第2組45,第3組67時因前面為5,故不符合,跳至下一字元78
### negative 2 behind
"01234567890".match(/[2-8]{2}(?<![5])/g)
結果: ["23", "56", "78"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,這裡取2個字元,故第1組23,當第2組45中遇到 5不符規則,跳至下一位元,第2組變56,第3組78 
### negative 1 front
"01234567890".match(/(?<![5])[2-8]/g)
結果: ["2", "3", "4", "5", "7", "8"]
分析: 因為 Lookbehind 在 front 時取值判斷不包含其值,這裡僅取1個字元,故「前值為5的6不合規則」
### negative 1 behind
"01234567890".match(/[2-8](?<![5])/g)
結果: ["2", "3", "4", "6", "7", "8"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,這裡取1個字元,故當 「非5」 時即為答案




2018-04-06

安裝 opencc 1.0.4 到 MAC 跟 CENTOS 平台下


[opencc 1.0.4 安裝]
1. 下載 opencc 1.0.4 => https://github.com/BYVoid/OpenCC
2. 解壓到你的程式下某目錄(自行依喜好安排)
3. 再來就是進到 opencc 的目錄執行
# cd opencc1.0.4
# mkdir build
# cd build
  產生 makefile, 以下分兩個平台, MAC 不能打開  GETTEXT
  CENTOS 執行以下命令
# cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release LE_GETTEXT:BOOL=ON  ..
  MAC 執行以下命令
# cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -D ENABLE_GETTEXT:BOOL=OFF  -DCMAKE_OSX_ARCHITECTURES=x86_64  .. 
# make
# sudo make install

4. 最後,用 pip 安裝 OpenCC 即可
$ pip install OpenCC==0.2


5. 若遇到 libopencc.so.2: cannot open shared object file: No such file or directory
那是因為build 出來的 library 是 32bit, centos 64bit 是放在 /usr/lib64/ 故建個捷徑連到 /usr/lib 即可

#sudo ln -s /usr/lib/libopencc.so.2 /usr/lib64/libopencc.so.2


[測試]
$ opencc --version

Open Chinese Convert (OpenCC) Command Line Tool
Version: 1.0.4



[python 測試]
$ python
Python 3.4.3 (default, Jul 13 2015, 03:19:09)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import opencc
>>> opencc.convert("开放中文转换", config='s2tw')
'開放中文轉換'
>>>




[內建可轉換檔有]
Conversions include 轉換包含:
'hk2s': Traditional Chinese (Hong Kong standard) to Simplified Chinese
's2hk': Simplified Chinese to Traditional Chinese (Hong Kong standard)
's2t': Simplified Chinese to Traditional Chinese
's2tw': Simplified Chinese to Traditional Chinese (Taiwan standard)
's2twp': Simplified Chinese to Traditional Chinese (Taiwan standard, with phrases)
't2hk': Traditional Chinese to Traditional Chinese (Hong Kong standard)
't2s': Traditional Chinese to Simplified Chinese
't2tw': Traditional Chinese to Traditional Chinese (Taiwan standard)
'tw2s': Traditional Chinese (Taiwan standard) to Simplified Chinese
'tw2sp': Traditional Chinese (Taiwan standard) to Simplified Chinese (with phrases)



2015-05-01

javascript 中文字長度判斷

因為現在網頁幾乎都是 utf8, 所以以往中文字會被判斷成2 bytes的問題現在都變成1了
例如
var s="中"
alert(s.length)
結果會顯示 1

那麼你若想要判斷 byte 的長度怎麼辦? (因為有時資料庫長度限制需求)
這裡有個網路上網友提供的好方法,速度快,又不用 regular express 或 encodeURIComponent 

2014-12-11

使用 jquery post data 進 django 系統

django 有 csrf 防止 cross site 攻擊,所以當你要使用 ajax post 到 django 時就會被擋。
解決方法有二:
第一是用 get, 例如:

2014-07-04

從 IP 查地理位置

從 IP 查地理位置

[Database]
http://lite.ip2location.com/main (內詳, 格式詳細, 分lite跟商業兩種版本)
http://db-ip.com/db/  (free + 收費版本)

DONATIONWARE
http://software77.net/geo-ip/
http://software77.net/geo-ip/?license

wget software77.net/geo-ip/?DL=1 -O /path/IpToCountry.csv.gz      IPV4 gzip
wget software77.net/geo-ip/?DL=2 -O /path/IpToCountry.csv.zip     IPV4 zip
wget software77.net/geo-ip/?DL=3 -O /path/IpToCountry.csv.MD5     IPV4 MD5 (CSV file)
wget software77.net/geo-ip/?DL=4 -O /path/IpToCountry.dat         IPV4 Geo::IPfree
wget software77.net/geo-ip/?DL=5 -O /path/IpToCountry.dat.MD5     IPV4 MD5 Geo::IPfree
wget software77.net/geo-ip/?DL=6 -O /path/country-codes.txt       Country Codes
wget software77.net/geo-ip/?DL=7 -O /path/IpToCountry.6R.csv.gz   IPV6 Ranges
wget software77.net/geo-ip/?DL=8 -O /path/IpToCountry.6R.csv.MD5  IPV6 Ranges MD5
wget software77.net/geo-ip/?DL=9 -O /path/IpToCountry.6C.csv.gz   IPV6 CIDR
wget software77.net/geo-ip/?DL=10 -O /path/IpToCountry.6C.csv.MD5 IPV6 CIDR MD5
Please NOTE the "/" before the "?"