2014-04-20 385 views
4

我花了相當一段時間後,決定發佈一個問題,但仍然沒有弄清楚問題所在。還讀了一堆看似相關的帖子,沒有一個真正適合我的簡單(?)問題。使用sed,正則表達式如何匹配中文字符?

所以我有一個包含華中國字符一個可能大的文本文件(> 1000線),與像採樣線:

"ref#2-5-1.jpg#2#一些 <variable> 內容#pic##" (the Chinese just means "some content"). 

所有需要修改的是一個空間應該之間插入每一個字符,如果沒有的話:

我天真地用類似下面簡單的東西開始,但沒有比賽在所有:

sed -e 's/\([\u4E00-\u9fff]\)/\1 /g' <test_utf_sed.txt > test_out.txt 

其中4E00-9fff應該是漢語普通話的代碼範圍。 Unamazingly,這並沒有工作,所以我也曾經想嘗試

sed -e 's/\([一-龻]\)/hello/g' <test_utf_sed.txt > test_out.txt 

這失敗,因爲我的bash無法顯示(?)中的「一」字。

然後我做了一些基本的測試,這也失敗了:

sed -e 's/\(\u4E00\)/hello/g' <test_utf_sed.txt > test_out.txt //一 
sed -e 's/\(\u4E9B\)/hello/g' <test_utf_sed.txt > test_out.txt //些 

同樣的,另一種符號來表示UTF編碼(這裏發現計算器):

sed -e 's/\(\u'U+4E00\)/hello/g' <test_utf_sed.txt > test_out.txt 

1)作爲工具來處理與雙字節字符,sed是正確的選擇?

2)是sed能處理Unicode的所有,還是我需要一個特殊的開關?

3)我不在尋找這樣一種解決方法解決方案:

step1: insert space after each character 
    //like 's/\(.\)/\1 /g') 
step2: remove space after each chacter which is not a Chinese character 
    //like 's/\([a-zA-Z0-9]\) /\1/g') 

我知道如何做到這一點,但它是unelegant而且容易出錯。這一定是可能的使用utf-8在sed中的正則表達式。

4)我的環境是的bash-3.2上的的MacOS 10.6.8(老氣OS)

5)如果你知道任何指點一下開正則表達式,如onliners庫處理中國文字或語言處理的,這將是巨大的佳品。

非常感謝提前,您的幫助深表感謝!

+0

http://stackoverflow.com/questions/8562354/remove-unicode-characters-from-textfiles-sed-other-bash-shell-methods – ooga

回答

4

Perl對處理Unicode有很好的支持。對於你的任務來說,這可能比sed更好。這一個班輪就像你的第一個SED例如:

perl -CIOED -p -e 's/\p{Block=CJK_Unified_Ideographs}/$& /g' filename 

-CIOED告訴Perl做它的I/O的UTF8。 -p爲輸入文件的每一行運行給定代碼一次,然後打印結果。 -e指定一行要運行的Perl代碼。有關命令行參數的更多信息,請參閱the documentation

正則表達式使用named ranges來標識要匹配的字符。

您可能還想閱讀Perl Unicode文檔。

+0

嗨!埃文,非常感謝,這工作:)我最後添加了一個「環視條件」,以確保只有在沒有空間時才添加空間:'perl -CIOED -p -e's/\ p {Block = CJK_Unified_Ideographs} **(?!)**/$&/ g'文件名' – sweetnsour

+0

感謝這樣一個整潔的答案,太棒了! –

2

sed不明白\u轉義序列(顯然)。我不知道bash-3.2是否也做,但我認爲它確實。如果是這樣,你可以寫

sed $'s/\u4E9B/hello/g' 

但你仍然無法做範圍規範。

然而,通過手動轉換爲UTF-8,你可以到達以下擴展正則表達式將,我相信,在U + 4E00範圍內的字符匹配任何UTF-8序列... U + 9FFF:

(\xe4[\xb8-\xbf][\x80-\xbf]|[\xe5-\xe9][\x80-\xbf][\x80-\xbf]) 

(但如果你在一個單字節語言調用sed,最好是C語言環境的字符範圍只會工作)

隨着GNU sed,你就會得到擴展正則表達式,如果你提供了-r fla G。與MacOSX我相信你需要-E標誌。所以,你可以嘗試:

LANG=C sed -E \ 
     $'s/(\xe4[\xb8-\xbf][\x80-\xbf]|[\xe5-\xe9][\x80-\xbf][\x80-\xbf])/\\1 /g' \ 
     <test_utf_sed.txt >test_out.txt 

(以上讓bash的處理\x逃逸如果你離開了$,然後sed將處理\x逃脫,但你必須要替代從\\1改變\1。我沒有Mac,也沒有舊版本的bash,所以我真的不知道你的sed是否做了十六進制轉義;我很確定你的bash會,但我不能保證它)。


順便說一句,它是爲這些角色獲取utf-8編碼並不難;我用原始文章中的一點點複製和粘貼來完成它。例如:

$ hd <<<"一些" 
00000000 e4 b8 80 e4 ba 9b 0a        |.......| 

它有助於瞭解該平面0表意文字(U + 4E00 ... U + 9FFF)的整個範圍內有三個字節碼,讓一爲E4 B8 80和些是E4 BA 9B。 (0A當然是線端。)

+0

嗨裏奇,非常感謝您對UTF-8進行調查和翻譯unicode!不幸的是,我得到一個錯誤(非法字節序列),儘管我試過這個非常簡單的字符串:'sed -E $'s/\(\ xe4 \)/ \ 1/g'> filename'。否則我會進一步追蹤這個想法。 – sweetnsour

+0

@Lena:中文字符的UTF-8代碼長度爲3個字節;在第一個字節('\ xe4')之後加一個空格將產生一個無效的字節序列。我不知道是什麼產生了這個錯誤,但它肯定沒有錯。對於一個簡單的例子,試試'\ xe4 \ xba \ x9b',它是些的utf-8代碼。雖然我在'sed'調用中忘記了一個小細節,看編輯(如果你在意)。 – rici

+0

低級評論:thx再次!讓我在週末看看這個。我不是專業的程序員(不再),所以閱讀需要一些時間。 – sweetnsour