亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Lua中的捕獲機制和轉換技巧介紹

2024-07-21 23:04:18
字體:
來源:轉載
供稿:網友

捕獲

捕獲是這樣一種機制:可以使用模式串的一部分匹配目標串的一部分。將你想捕獲的模式用圓括號括起來,就指定了一個捕獲。

在string.find使用捕獲的時候,函數會返回捕獲的值作為額外的結果。這常被用來將一個目標串拆分成多個:

復制代碼 代碼如下:

pair = "name = Anna"
_, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)")
print(key, value)    --> name  Anna

 

'%a+' 表示菲空的字母序列;'%s*' 表示0個或多個空白。在上面的例子中,整個模式代表:一個字母序列,后面是任意多個空白,然后是 '=' 再后面是任意多個空白,然后是一個字母序列。兩個字母序列都是使用圓括號括起來的子模式,當他們被匹配的時候,他們就會被捕獲。當匹配發生的時候,find函數總是先返回匹配串的索引下標(上面例子中我們存儲啞元變量 _ 中),然后返回子模式匹配的捕獲部分。下面的例子情況類似:

 

復制代碼 代碼如下:

date = "17/7/1990"
_, _, d, m, y = string.find(date, "(%d+)/(%d+)/(%d+)")
print(d, m, y)      --> 17 7 1990   

 

我們可以在模式中使用向前引用,'%d'(d代表1-9的數字)表示第d個捕獲的拷貝。

看個例子,假定你想查找一個字符串中單引號或者雙引號引起來的子串,你可能使用模式 '["'].-["']',但是這個模式對處理類似字符串 "it's all right" 會出問題。為了解決這個問題,可以使用向前引用,使用捕獲的第一個引號來表示第二個引號:

復制代碼 代碼如下:

s = [[then he said: "it's all right"!]]
a, b, c, quotedPart = string.find(s, "(["'])(.-)%1")
print(quotedPart)    --> it's all right
print(c)            --> " 

第一個捕獲是引號字符本身,第二個捕獲是引號中間的內容('.-' 匹配引號中間的子串)。

 

捕獲值的第三個應用是用在函數gsub中。與其他模式一樣,gsub的替換串可以包含 '%d',當替換發生時他被轉換為對應的捕獲值。(順便說一下,由于存在這些情況,替換串中的字符 '%' 必須用 "%%" 表示)。下面例子中,對一個字符串中的每一個字母進行復制,并用連字符將復制的字母和原字母連接起來:

 

復制代碼 代碼如下:

print(string.gsub("hello Lua!", "(%a)", "%1-%1"))
    --> h-he-el-ll-lo-o L-Lu-ua-a! 

下面代碼互換相鄰的字符:
復制代碼 代碼如下:

print(string.gsub("hello Lua", "(.)(.)", "%2%1"))
    --> ehll ouLa 

 

讓我們看一個更有用的例子,寫一個格式轉換器:從命令行獲取LaTeX風格的字符串,形如:

 

復制代碼 代碼如下:

/command{some text}

將它們轉換為XML風格的字符串:
復制代碼 代碼如下:

<command>some text</command>

對于這種情況,下面的代碼可以實現這個功能:
復制代碼 代碼如下:

s = string.gsub(s, "//(%a+){(.-)}", "<%1>%2</%1>") 

比如,如果字符串s為:
復制代碼 代碼如下:

the /quote{task} is to /em{change} that.

調用gsub之后,轉換為:
復制代碼 代碼如下:

the <quote>task</quote> is to change that.

 

另一個有用的例子是去除字符串首尾的空格:

復制代碼 代碼如下:

function trim (s)
    return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end 

注意模式串的用法,兩個定位符('^' 和 '$')保證我們獲取的是整個字符串。因為,兩個 '%s*' 匹配首尾的所有空格,'.-' 匹配剩余部分。還有一點需要注意的是gsub返回兩個值,我們使用額外的圓括號丟棄多余的結果(替換發生的次數)。

 

最后一個捕獲值應用之處可能是功能最強大的。我們可以使用一個函數作為string.gsub的第三個參數調用gsub。在這種情況下,string.gsub每次發現一個匹配的時候就會調用給定的作為參數的函數,捕獲值可以作為被調用的這個函數的參數,而這個函數的返回值作為gsub的替換串。先看一個簡單的例子,下面的代碼將一個字符串中全局變量$varname出現的地方替換為變量varname的值:

復制代碼 代碼如下:

function expand (s)
    s = string.gsub(s, "$(%w+)", function (n)
      return _G[n]
    end)
    return s
end

 

name = "Lua"; status = "great"
print(expand("$name is $status, isn't it?"))

--> Lua is great, isn't it?


如果你不能確定給定的變量是否為string類型,可以使用tostring進行轉換:
復制代碼 代碼如下:

function expand (s)
    return (string.gsub(s, "$(%w+)", function (n)
      return tostring(_G[n])
    end))
end

 

print(expand("print = $print; a = $a"))

--> print = function: 0x8050ce0; a = nil

 


下面是一個稍微復雜點的例子,使用loadstring來計算一段文本內$后面跟著一對方括號內表達式的值:
復制代碼 代碼如下:

s = "sin(3) = $[math.sin(3)]; 2^5 = $[2^5]"
print((string.gsub(s, "$(%b[])", function (x)
    x = "return " .. string.sub(x, 2, -2)
    local f = loadstring(x)
    return f()
end)))

 

--> sin(3) = 0.1411200080598672; 2^5 = 32


第一次匹配是 "$[math.sin(3)]",對應的捕獲為 "[math.sin(3)]",調用string.sub去掉首尾的方括號,
所以被加載執行的字符串是 "return math.sin(3)","$[2^5]" 的匹配情況類似。
我們常常需要使用string.gsub遍歷字符串,而對返回結果不感興趣。比如,我們收集一個字符串中所有的單詞,然后插入到一個表中:
復制代碼 代碼如下:

words = {}
string.gsub(s, "(%a+)", function (w)
    table.insert(words, w)
end)

如果字符串s為 "hello hi, again!",上面代碼的結果將是:
復制代碼 代碼如下:

{"hello", "hi", "again"}

使用string.gfind函數可以簡化上面的代碼:
復制代碼 代碼如下:

words = {}
for w in string.gfind(s, "(%a)") do
    table.insert(words, w)
end

gfind函數比較適合用于范性for循環。他可以遍歷一個字符串內所有匹配模式的子串。我們可以進一步的簡化上面的代碼,調用gfind函數的時候,如果不顯示的指定捕獲,函數將捕獲整個匹配模式。所以,上面代碼可以簡化為:
復制代碼 代碼如下:

words = {}
for w in string.gfind(s, "%a") do
    table.insert(words, w)
end

下面的例子我們使用URL編碼,URL編碼是HTTP協議來用發送URL中的參數進行的編碼。這種編碼將一些特殊字符(比如 '='、'&'、'+')轉換為 "%XX" 形式的編碼,其中XX是字符的16進制表示,然后將空白轉換成 '+'。比如,將字符串 "a+b = c" 編碼為 "a%2Bb+%3D+c"。最后,將參數名和參數值之間加一個 '=';在name=value對之間加一個 "&"。比如字符串:
name = "al"; query = "a+b = c";  q="yes or no"
被編碼為:
復制代碼 代碼如下:

name=al&query=a%2Bb+%3D+c&q=yes+or+no

現在,假如我們想將這URL解碼并把每個值存儲到表中,下標為對應的名字。下面的函數實現了解碼功能:
復制代碼 代碼如下:

function unescape (s)
    s = string.gsub(s, "+", " ")
    s = string.gsub(s, "%%(%x%x)", function (h)
      return string.char(tonumber(h, 16))
    end)
    return s
end

第一個語句將 '+' 轉換成空白,第二個gsub匹配所有的 '%' 后跟兩個數字的16進制數,然后調用一個匿名函數,匿名函數將16進制數轉換成一個數字(tonumber在16進制情況下使用的)然后再轉化為對應的字符。比如:
復制代碼 代碼如下:

print(unescape("a%2Bb+%3D+c"))    --> a+b = c

對于name=value對,我們使用gfind解碼,因為names和values都不能包含 '&' 和 '='我們可以用模式 '[^&=]+' 匹配他們:
復制代碼 代碼如下:

cgi = {}
function decode (s)
    for name, value in string.gfind(s, "([^&=]+)=([^&=]+)") do
      name = unescape(name)
      value = unescape(value)
      cgi[name] = value
    end
end

調用gfind函數匹配所有的name=value對,對于每一個name=value對,迭代子將其相對應的捕獲的值返回給變量name和value。循環體內調用unescape函數解碼name和value部分,并將其存儲到cgi表中。

 

與解碼對應的編碼也很容易實現。首先,我們寫一個escape函數,這個函數將所有的特殊字符轉換成 '%' 后跟字符對應的ASCII碼轉換成兩位的16進制數字(不足兩位,前面補0),然后將空白轉換為 '+':

復制代碼 代碼如下:

function escape (s)
    s = string.gsub(s, "([&=+%c])", function (c)
      return string.format("%%%02X", string.byte(c))
    end)
    s = string.gsub(s, " ", "+")
    return s
end

編碼函數遍歷要被編碼的表,構造最終的結果串:
復制代碼 代碼如下:

function encode (t)
    local s = ""
    for k,v in pairs(t) do
      s = s .. "&" .. escape(k) .. "=" .. escape(v)
    end
    return string.sub(s, 2)    -- remove first `&'
end
t = {name = "al", query = "a+b = c", q="yes or no"}
print(encode(t)) --> q=yes+or+no&query=a%2Bb+%3D+c&name=al

 

轉換的技巧(Tricks of the Trade)

模式匹配對于字符串操縱來說是強大的工具,你可能只需要簡單的調用string.gsub和find就可以完成復雜的操作,然而,因為它功能強大你必須謹慎的使用它,否則會帶來意想不到的結果。

對正常的解析器而言,模式匹配不是一個替代品。對于一個quick-and-dirty程序,你可以在源代碼上進行一些有用的操作,但很難完成一個高質量的產品。前面提到的匹配C程序中注釋的模式是個很好的例子:'/%*.-%*/'。如果你的程序有一個字符串包含了"/*",最終你將得到錯誤的結果:
 

復制代碼 代碼如下:

test = [[char s[] = "a /* here"; /* a tricky string */]]
print(string.gsub(test, "/%*.-%*/", "<COMMENT>"))
    --> char s[] = "a <COMMENT>


雖然這樣內容的字符串很罕見,如果是你自己使用的話上面的模式可能還湊活。但你不能將一個帶有這種毛病的程序作為產品出售。

 

一般情況下,Lua中的模式匹配效率是不錯的:一個奔騰333MHz機器在一個有200K字符的文本內匹配所有的單詞(30K的單詞)只需要1/10秒。但是你不能掉以輕心,應該一直對不同的情況特殊對待,盡可能的更明確的模式描述。一個限制寬松的模式比限制嚴格的模式可能慢很多。一個極端的例子是模式 '(.-)%$' 用來獲取一個字符串內$符號以前所有的字符,如果目標串中存在$符號,沒有什么問題;但是如果目標串中不存在$符號。上面的算法會首先從目標串的第一個字符開始進行匹配,遍歷整個字符串之后沒有找到$符號,然后從目標串的第二個字符開始進行匹配,……這將花費原來平方次冪的時間,導致在一個奔騰333MHz的機器中需要3個多小時來處理一個200K的文本串??梢允褂孟旅孢@個模式避免上面的問題 '^(.-)%$'。定位符^告訴算法如果在第一個位置沒有沒找到匹配的子串就停止查找。使用這個定位符之后,同樣的環境也只需要不到1/10秒的時間。

也需要小心空模式:匹配空串的模式。比如,如果你打算用模式 '%a*' 匹配名字,你會發現到處都是名字:
 

復制代碼 代碼如下:

i, j = string.find(";$% **#$hello13", "%a*")
print(i,j)    --> 1 0


這個例子中調用string.find正確的在目標串的開始處匹配了空字符。永遠不要寫一個以 '-' 開頭或者結尾的模式,因為它將匹配空串。這個修飾符得周圍總是需要一些東西來定位他的擴展。相似的,一個包含 '.*' 的模式是一個需要注意的,因為這個結構可能會比你預算的擴展的要多。

 

有時候,使用Lua本身構造模式是很有用的??匆粋€例子,我們查找一個文本中行字符大于70個的行,也就是匹配一個非換行符之前有70個字符的行。我們使用字符類'[^/n]'表示非換行符的字符。所以,我們可以使用這樣一個模式來滿足我們的需要:重復匹配單個字符的模式70次,后面跟著一個匹配一個字符0次或多次的模式。我們不手工來寫這個最終的模式,而使用函數string.rep:
 

復制代碼 代碼如下:

pattern = string.rep("[^/n]", 70) .. "[^/n]*"


另一個例子,假如你想進行一個大小寫無關的查找。方法之一是將任何一個字符x變為字符類 '[xX]'。我們也可以使用一個函數進行自動轉換:

復制代碼 代碼如下:

function nocase (s)
    s = string.gsub(s, "%a", function (c)
      return string.format("[%s%s]", string.lower(c),
                                          string.upper(c))
    end)
    return s
end

 

print(nocase("Hi there!"))
    --> [hH][iI] [tT][hH][eE][rR][eE]!



有時候你可能想要將字符串s1轉化為s2,而不關心其中的特殊字符。如果字符串s1和s2都是字符串序列,你可以給其中的特殊字符加上轉義字符來實現。但是如果這些字符串是變量呢,你可以使用gsub來完成這種轉義:

復制代碼 代碼如下:

s1 = string.gsub(s1, "(%W)", "%%%1")
s2 = string.gsub(s2, "%%", "%%%%")


在查找串中,我們轉義了所有的非字母的字符。在替換串中,我們只轉義了 '%' 。另一個對模式匹配而言有用的技術是在進行真正處理之前,對目標串先進行預處理。一個預處理的簡單例子是,將一段文本內的雙引號內的字符串轉換為大寫,但是要注意雙引號之間可以包含轉義的引號("""):

這是一個典型的字符串例子:

復制代碼 代碼如下:

"This is "great"!".


我們處理這種情況的方法是,預處理文本把有問題的字符序列轉換成其他的格式。比如,我們可以將 """ 編碼為 "/1",但是如果原始的文本中包含 "/1",我們又陷入麻煩之中。一個避免這個問題的簡單的方法是將所有 "/x" 類型的編碼為 "/ddd",其中ddd是字符x的十進制表示:

復制代碼 代碼如下:

function code (s)
    return (string.gsub(s, "//(.)", function (x)
      return string.format("//%03d", string.byte(x))
    end))
end


注意,原始串中的 "/ddd" 也會被編碼,解碼是很容易的:

復制代碼 代碼如下:

function decode (s)
    return (string.gsub(s, "//(%d%d%d)", function (d)
      return "/" .. string.char(d)
    end))
end


如果被編碼的串不包含任何轉義符,我們可以簡單的使用 ' ".-" ' 來查找雙引號字符串:

復制代碼 代碼如下:

s = [[follows a typical string: "This is "great"!".]]
s = code(s)
s = string.gsub(s, '(".-")', string.upper)
s = decode(s)
print(s)
    --> follows a typical string: "THIS IS "GREAT"!".


更緊縮的形式:

復制代碼 代碼如下:

print(decode(string.gsub(code(s), '(".-")', string.upper)))


我們回到前面的一個例子,轉換/command{string}這種格式的命令為XML風格:

復制代碼 代碼如下:

<command>string</command>


但是這一次我們原始的格式中可以包含反斜杠作為轉義符,這樣就可以使用"/"、"/{" 和 "/}",分別表示 '/'、'{' 和 '}'。為了避免命令和轉義的字符混合在一起,我們應該首先將原始串中的這些特殊序列重新編碼,然而,與上面的一個例子不同的是,我們不能轉義所有的 /x,因為這樣會將我們的命令(/command)也轉換掉。這里,我們僅當x不是字符的時候才對 /x 進行編碼:

復制代碼 代碼如下:

function code (s)
    return (string.gsub(s, '//(%A)', function (x)
      return string.format(" //%03d ", string.byte(x))
    end))
end


解碼部分和上面那個例子類似,但是在最終的字符串中不包含反斜杠,所以我們可直接調用string.char:

復制代碼 代碼如下:

function decode (s)
    return (string.gsub(s, '//(%d%d%d)', string.char))
end

 

s = [[a /emph{command} is written as // command/{text/}.]]
s = code(s)
s = string.gsub(s, "// (%a+){(.-)}", "<%1>%2</%1>")

print(decode(s))
--> a <emph>command</emph> is written as /command{text}.



我們最后一個例子是處理CSV(逗號分割)的文件,很多程序都使用這種格式的文本,比如Microsoft Excel。CSV文件十多條記錄的列表,每一條記錄一行,一行內值與值之間逗號分割,如果一個值內也包含逗號這個值必須用雙引號引起來,如果值內還包含雙引號,需使用雙引號轉義雙引號(就是兩個雙引號表示一個),看例子,下面的數組:

復制代碼 代碼如下:

{'a b', 'a,b', 'a,"b"c', 'hello "world"!', }


可以看作為:

復制代碼 代碼如下:

a b,"a,b"," a,""b""c", hello "world"!,


將一個字符串數組轉換為CSV格式的文件是非常容易的。我們要做的只是使用逗號將所有的字符串連接起來:

復制代碼 代碼如下:

function toCSV (t)
    local s = ""
    for _,p in pairs(t) do
      s = s .. "," .. escapeCSV(p)
    end
    return string.sub(s, 2)    -- remove first comma
end


如果一個字符串包含逗號活著引號在里面,我們需要使用引號將這個字符串引起來,并轉義原始的引號:

復制代碼 代碼如下:

function escapeCSV (s)
    if string.find(s, '[,"]') then
      s = '"' .. string.gsub(s, '"', '""') .. '"'
    end
    return s
end


將CSV文件內容存放到一個數組中稍微有點難度,因為我們必須區分出位于引號中間的逗號和分割域的逗號。我們可以設法轉義位于引號中間的逗號,然而并不是所有的引號都是作為引號存在,只有在逗號之后的引號才是一對引號的開始的那一個。只有不在引號中間的逗號才是真正的逗號。這里面有太多的細節需要注意,比如,兩個引號可能表示單個引號,可能表示兩個引號,還有可能表示空:

復制代碼 代碼如下:

"hello""hello", "",""


這個例子中,第一個域是字符串 "hello"hello",第二個域是字符串 " """(也就是一個空白加兩個引號),最后一個域是一個空串。

 

我們可以多次調用gsub來處理這些情況,但是對于這個任務使用傳統的循環(在每個域上循環)來處理更有效。循環體的主要任務是查找下一個逗號;并將域的內容存放到一個表中。對于每一個域,我們循環查找封閉的引號。循環內使用模式 ' "("?) ' 來查找一個域的封閉的引號:如果一個引號后跟著一個引號,第二個引號將被捕獲并賦給一個變量c,意味著這仍然不是一個封閉的引號。

 

復制代碼 代碼如下:

function fromCSV (s)
    s = s .. ','      -- ending comma
    local t = {}      -- table to collect fields
    local fieldstart = 1
    repeat
      -- next field is quoted? (start with `"'?)
      if string.find(s, '^"', fieldstart) then
      local a, c
      local i = fieldstart
      repeat
          -- find closing quote
          a, i, c = string.find(s, '"("?)', i+1)
      until c ~= '"'    -- quote not followed by quote?
      if not i then error('unmatched "') end
          local f = string.sub(s, fieldstart+1, i-1)
          table.insert(t, (string.gsub(f, '""', '"')))
          fieldstart = string.find(s, ',', i) + 1
      else              -- unquoted; find next comma
          local nexti = string.find(s, ',', fieldstart)
          table.insert(t, string.sub(s, fieldstart,
                                              nexti-1))
          fieldstart = nexti + 1
      end
    until fieldstart > string.len(s)
    return t
end

 

t = fromCSV('"hello "" hello", "",""')
for i, s in ipairs(t) do print(i, s) end
    --> 1      hello " hello
    --> 2        ""
    --> 3

 

 
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品日韩在线播放| 亚洲精品国产精品乱码不99按摩| 久久久精品欧美| 亚洲精品国产精品国自产观看浪潮| 精品国产91久久久| 国产精品免费小视频| 在线播放日韩专区| 欧美日韩国产麻豆| 精品久久香蕉国产线看观看gif| 久久久久久九九九| 日韩成人激情影院| 一区二区三区天堂av| 成人在线精品视频| 久久久亚洲天堂| 欧美大片网站在线观看| 成人免费网站在线看| 久久久精品影院| 欧美大片在线影院| 日韩高清免费在线| 欧美国产精品日韩| 欧美日本中文字幕| 欧美刺激性大交免费视频| 在线成人免费网站| 麻豆国产va免费精品高清在线| 精品久久久一区二区| 国产日产欧美a一级在线| 国产精品都在这里| 2019亚洲男人天堂| 奇米成人av国产一区二区三区| 欧美成人在线影院| 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲精品大尺度| 色视频www在线播放国产成人| 久久免费精品视频| 亚洲精品小视频在线观看| 欧美色图在线视频| 国产精品成av人在线视午夜片| 欧美性高潮床叫视频| 日韩大陆欧美高清视频区| 亚洲日韩欧美视频| 国产视频久久久久久久| 国产精品视频最多的网站| 国产精品久久久久久久久借妻| 91高清免费在线观看| 91精品国产自产在线| 丝袜情趣国产精品| 91国产精品视频在线| 亚洲美女精品久久| 国产精品久久久久91| 丰满岳妇乱一区二区三区| 日韩欧美精品在线观看| 欧美激情欧美狂野欧美精品| 日韩欧美精品在线观看| 国产亚洲精品综合一区91| 中文字幕免费精品一区高清| 久久久中文字幕| 日韩欧美福利视频| 精品一区二区三区四区| 日韩精品黄色网| 国产精品a久久久久久| 在线观看欧美www| 久久久天堂国产精品女人| 91成品人片a无限观看| 97人人做人人爱| 日韩免费观看网站| 77777少妇光屁股久久一区| 中文日韩电影网站| 亚洲自拍偷拍区| 久久视频免费在线播放| 亚洲精品中文字幕av| 日韩欧美在线免费| 韩日精品中文字幕| 自拍偷拍免费精品| 亚洲电影av在线| 欧美激情精品久久久久久黑人| 欧美精品在线免费播放| 精品性高朝久久久久久久| 国产精品xxxxx| 欧美不卡视频一区发布| 日韩中文字幕视频| 热99久久精品| 日韩电影视频免费| 青青久久av北条麻妃海外网| 在线播放亚洲激情| 亚洲无线码在线一区观看| 国产精品久久久久久av福利软件| 国产成人91久久精品| 国产精品视频久久久久| 欧美国产日韩视频| 91在线免费看网站| 国产精品视频最多的网站| 国产在线一区二区三区| 69久久夜色精品国产69| 日韩免费视频在线观看| 岛国av午夜精品| 欧美黑人狂野猛交老妇| 亚洲永久免费观看| 日韩av中文字幕在线| 亚洲天堂av高清| 欧美极品在线视频| 亚洲欧美日韩天堂一区二区| 国产久一一精品| 亚洲精品色婷婷福利天堂| 欧美性生交xxxxxdddd| 日韩精品免费一线在线观看| 91精品国产自产91精品| 成人妇女免费播放久久久| 午夜欧美大片免费观看| 欧美成人精品在线播放| 亚洲精品91美女久久久久久久| 色婷婷av一区二区三区久久| 91中文字幕在线观看| 成人性生交大片免费观看嘿嘿视频| 日韩欧美在线观看| 亚洲色图色老头| 久久亚洲私人国产精品va| 中文字幕久久久| 欧美日韩午夜视频在线观看| 成人动漫网站在线观看| 欧美极品少妇xxxxx| 成人网在线免费看| 日韩中文在线中文网三级| 亚洲精品一二区| 日韩在线视频中文字幕| 国产精品久久久久国产a级| 91丝袜美腿美女视频网站| 日韩日本欧美亚洲| 国产日韩换脸av一区在线观看| 奇门遁甲1982国语版免费观看高清| 国产精品美女av| 亚洲bt欧美bt日本bt| 国产欧美日韩视频| 久久亚洲国产精品成人av秋霞| 日韩有码片在线观看| 国产亚洲视频中文字幕视频| 成人激情黄色网| 91久久国产精品91久久性色| 欧美在线视频免费播放| 日本一区二区在线免费播放| 欧美超级免费视 在线| 国产精国产精品| 欧美日韩亚洲91| 国产精品成人一区二区三区吃奶| 97av在线视频免费播放| 久久精品国产视频| 欧美极品美女电影一区| 一区二区三欧美| 成人久久18免费网站图片| 97久久久久久| 亚洲日本欧美中文幕| 欧美亚洲另类制服自拍| 欧美老女人性生活| 久久久久久成人| 亚洲高清在线观看| 亚洲区在线播放| 人人做人人澡人人爽欧美| 久久伊人精品视频| 亚洲二区中文字幕| 久久在线免费视频| 国产精品美女久久久免费| 欧美日韩国产色| 欧美在线影院在线视频| 国产成人精品国内自产拍免费看| 亚洲福利在线播放|