Lua 語系

lua-users home
wiki

以下是一些關於 Lua 中 [語系] 的註解。

Lua 深受標準 C 的影響,因此 C 中許多關於語系的處理方式都會傳遞資訊給 Lua。

可以使用 [os.setlocale] 函式取得或設定目前的語系。

警告:os.setlocale 會在內部呼叫 C 中的 [setlocale] 函式,而此函式會同時設定所有 Lua 狀態和目前處理程序中所有作業系統執行緒的語系。不過,有些 C 實作會提供非標準函式(例如 Microsoft 的 [setlocale])來只影響目前的作業系統執行緒。

[PiL 22.2] 中關於語系的簡要背景資料(注意:請參閱下方的歷史備忘)。

Lua 語法

在 Lua 5.1 中,Lua 語言中的識別元是依語系而定的 [1]。在 5.2 中,Lua 識別元不能使用依語系而定的字元 [2]

Lua 程式碼中的數字必須撰寫成 C 語系的樣式

print(1.23) -- always valid
print(1,23) -- always interpreted as two numbers: "1" and "23".

針對數字的測試

> assert(os.setlocale('fr_FR'))
> = 1,23 , 1.23
1	23	1,23
> =loadstring("return 1,23 , 1.23")()
1	23	1,23
> print(1.23, tostring(1.23), string.format("%0.2f",1.23))
1,23	1,23	1,23
> 
> ="1.23" + 0
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
	stdin:1: in main chunk
	[C]: in ?
> ="1,23" + 0
1,23
> =tonumber("1.23"), tonumber("1,23")
nil	1,23

以上測試可能會受 luaconf.h 設定的影響,而在 5.2.0rc2 中有下列說明:

/*
@@ lua_str2number converts a decimal numeric string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' do both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
*/
#define lua_str2number(s,p)	strtod((s), (p))

#if defined(LUA_USE_STRTODHEX)
#define lua_strx2number(s,p)	strtod((s), (p))
#endif

如果你停用 LUA_USE_STRTODHEX,那會使用 Lua 自己實作的 lua_strx2number。這依賴於與語系無關的函式(例如 lctype.c 中的 lisspace)。觀察奇怪的行為

Lua 5.2.0  Copyright (C) 1994-2011 Lua.org, PUC-Rio
> assert(os.setlocale'fr_FR')
> return tonumber'1.5', tonumber'1,5'
nil	1,5
> return tonumber'0x1.5', tonumber'0x1,5'
1,3125	nil

針對字元類別的測試

function findrange(pat)
  for i=0,255 do
    if string.char(i):match(pat) then
      print(i, string.char(i))
    end
  end
end

assert(os.setlocale'C')
findrange'%a' --> A-Z,a-z
assert(os.setlocale'en_US.ISO-8859-1')
findrange'%a' --> A-Z,a-z,\170,\181,\186,\192-\255
findrange'%l' --> a-z,\181,\223-\255

像 isspace(%w)和 isdigit(%d)等其他類別可能可以傳回比 C 語系的結果更多 [3]

string.lowerstring.upper 也與語系相關。

字串比較

> assert(os.setlocale'C')
> return "�" < "e"
false
> assert(os.setlocale('fr_FR'))
> return "�" < "e"
true

針對日期的測試

> assert(os.setlocale('C'))
> =os.date()
Sat Nov 26 13:22:56 2011
> assert(os.setlocale('fr_FR'))
> =os.date()
sam. 26 nov. 2011 13:22:56 EST

歷史備忘

-- This error occurred in 5.0 (but not 5.1 or above)
-- https://lua.dev.org.tw/pil/22.2.html
print(os.setlocale('pt_BR'))    --> pt_BR (Portuguese-Brazil)
print(3,4)                      --> 3    4
print(3.4)       --> stdin:1: malformed number near `3.4'

請參閱


RecentChanges · 喜好設定
編輯 · 歷史
最後編輯於 2018 年 1 月 4 日,星期四,上午 12:55 GMT (diff)