programing

루아에서 줄 쪼개기?

newstyles 2023. 7. 28. 21:52

루아에서 줄 쪼개기?

간단하게 줄을 쪼개야 하는데, 이것에 대한 기능이 없는 것 같고, 테스트한 수동 방식이 작동하지 않는 것 같았습니다.어떻게 하면 좋을까요?

여기 저의 정말 간단한 해결책이 있습니다.을 합니다.gmatch()원하는 구분자 이외의 문자를 하나 이상 포함하는 문자열을 캡처하는 함수.구분 기호는 임의의 공백입니다(%s기본적으로 Lua):

function mysplit (inputstr, sep)
        if sep == nil then
                sep = "%s"
        end
        local t={}
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                table.insert(t, str)
        end
        return t
end

Lua에서 문자열을 분할하는 경우 string.gmatch() 또는 string.sub() 메서드를 사용해 보십시오.문자열을 분할할 인덱스를 알고 있는 경우 string.sub() 메서드를 사용하고, 문자열을 구문 분석하여 문자열을 분할할 위치를 찾으려면 string.gmatch()를 사용합니다.

Lua 5.1 참조 매뉴얼의 string.gmatch()를 사용한 예:

 t = {}
 s = "from=world, to=Lua"
 for k, v in string.gmatch(s, "(%w+)=(%w+)") do
   t[k] = v
 end

토큰을 반복하고 싶다면, 이것은 매우 깔끔합니다.

line = "one, two and 3!"

for token in string.gmatch(line, "[^%s]+") do
   print(token)
end

출력:

하나.

두명

그리고.

3!

간단한 설명: "[^%s]+" 패턴은 공백 문자 사이의 비어 있지 않은 모든 문자열과 일치합니다.

럼처입니다.string.gmatch문자열에서 패턴을 찾고, 이 함수는 패턴 사이의 것을 찾습니다.

function string:split(pat)
  pat = pat or '%s+'
  local st, g = 1, self:gmatch("()("..pat..")")
  local function getter(segs, seps, sep, cap1, ...)
    st = sep and seps + #sep
    return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
  end
  return function() if st then return getter(st, g()) end end
end

기본적으로 공백으로 구분된 모든 항목을 반환합니다.

기능은 다음과 같습니다.

function split(pString, pPattern)
   local Table = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat = "(.-)" .. pPattern
   local last_end = 1
   local s, e, cap = pString:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~= "" then
     table.insert(Table,cap)
      end
      last_end = e+1
      s, e, cap = pString:find(fpat, last_end)
   end
   if last_end <= #pString then
      cap = pString:sub(last_end)
      table.insert(Table, cap)
   end
   return Table
end

다음과 같이 부릅니다.

list=split(string_to_split,pattern_to_match)

예:

list=split("1:2:3:4","\:")


자세한 내용은 여기를 참조하십시오.
http://lua-users.org/wiki/://lua-users.org/wiki/SplitJoin

고양이의 가죽을 벗기는 방법은 여러 가지가 있기 때문에 제 접근법은 다음과 같습니다.

코드:

#!/usr/bin/env lua

local content = [=[
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna 
aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
ullamco laboris nisi ut aliquip ex ea commodo consequat.
]=]

local function split(str, sep)
   local result = {}
   local regex = ("([^%s]+)"):format(sep)
   for each in str:gmatch(regex) do
      table.insert(result, each)
   end
   return result
end

local lines = split(content, "\n")
for _,line in ipairs(lines) do
   print(line)
end

출력: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

설명:

gmatch함수는 반복기로 작동하며 일치하는 모든 문자열을 가져옵니다.regex.regex구분 기호를 찾을 때까지 모든 문자를 사용합니다.

이러한 답변의 대부분은 단일 문자 구분 기호만 허용하거나 에지 사례(예: 빈 구분 기호)를 잘 처리하지 못하므로 보다 확실한 솔루션을 제공해야 한다고 생각했습니다.

두 기능이 .gsplit그리고.split위키백과와 같은 위키에서 사용되는 미디어위키 확장자로 스크리본의 코드를 수정했습니다.이 코드는 GPL v2에 따라 라이센스가 부여됩니다.코드를 조금 더 쉽게 이해할 수 있도록 변수 이름을 변경하고 주석을 추가했으며, 유니코드 문자열에 대해 Scribunto의 패턴 대신 일반 Lua 문자열 패턴을 사용하도록 코드를 변경했습니다.원래 코드는 여기에 테스트 케이스가 있습니다.

-- gsplit: iterate over substrings in a string separated by a pattern
-- 
-- Parameters:
-- text (string)    - the string to iterate over
-- pattern (string) - the separator pattern
-- plain (boolean)  - if true (or truthy), pattern is interpreted as a plain
--                    string, not a Lua pattern
-- 
-- Returns: iterator
--
-- Usage:
-- for substr in gsplit(text, pattern, plain) do
--   doSomething(substr)
-- end
local function gsplit(text, pattern, plain)
  local splitStart, length = 1, #text
  return function ()
    if splitStart then
      local sepStart, sepEnd = string.find(text, pattern, splitStart, plain)
      local ret
      if not sepStart then
        ret = string.sub(text, splitStart)
        splitStart = nil
      elseif sepEnd < sepStart then
        -- Empty separator!
        ret = string.sub(text, splitStart, sepStart)
        if sepStart < length then
          splitStart = sepStart + 1
        else
          splitStart = nil
        end
      else
        ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or ''
        splitStart = sepEnd + 1
      end
      return ret
    end
  end
end

-- split: split a string into substrings separated by a pattern.
-- 
-- Parameters:
-- text (string)    - the string to iterate over
-- pattern (string) - the separator pattern
-- plain (boolean)  - if true (or truthy), pattern is interpreted as a plain
--                    string, not a Lua pattern
-- 
-- Returns: table (a sequence table containing the substrings)
local function split(text, pattern, plain)
  local ret = {}
  for match in gsplit(text, pattern, plain) do
    table.insert(ret, match)
  end
  return ret
end

의 몇 split사용 중인 기능:

local function printSequence(t)
  print(unpack(t))
end

printSequence(split('foo, bar,baz', ',%s*'))       -- foo     bar     baz
printSequence(split('foo, bar,baz', ',%s*', true)) -- foo, bar,baz
printSequence(split('foo', ''))                    -- f       o       o

나는 이 짧은 해결책이 좋습니다.

function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

다음 방법을 사용할 수 있습니다.

function string:split(delimiter)
  local result = { }
  local from  = 1
  local delim_from, delim_to = string.find( self, delimiter, from  )
  while delim_from do
    table.insert( result, string.sub( self, from , delim_from-1 ) )
    from  = delim_to + 1
    delim_from, delim_to = string.find( self, delimiter, from  )
  end
  table.insert( result, string.sub( self, from  ) )
  return result
end

delimiter = string.split(stringtodelimite,pattern) 

남에게서 볼 수 없는 방법

local function str_split(str, sep)
    local sep, res = sep or '%s', {}
    string.gsub(str, '[^'..sep..']+', function(x) res[#res+1] = x end)
    return res 
end

구분 기호에 간단히 표시

local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
    print(x)
end

펜라이트 라이브러리를 사용할 수 있습니다.이것은 출력 목록의 구분 기호를 사용하여 문자열을 분할하는 기능을 가지고 있습니다.

Lua에서 프로그래밍하고 누락하는 동안 필요할 수 있는 많은 기능을 구현했습니다.

여기 그것을 사용하기 위한 샘플이 있습니다.

> 
> stringx = require "pl.stringx"
> 
> str = "welcome to the world of lua"
> 
> arr = stringx.split(str, " ")
> 
> arr
{welcome,to,the,world,of,lua}
> 

저는 위의 예들을 사용하여 저만의 기능을 만들었습니다.하지만 제게 부족한 부분은 자동적으로 탈출하는 마법 캐릭터였습니다.

여기 제 기여가 있습니다.

function split(text, delim)
    -- returns an array of fields based on text and delimiter (one character only)
    local result = {}
    local magic = "().%+-*?[]^$"

    if delim == nil then
        delim = "%s"
    elseif string.find(delim, magic, 1, true) then
        -- escape magic
        delim = "%"..delim
    end

    local pattern = "[^"..delim.."]+"
    for w in string.gmatch(text, pattern) do
        table.insert(result, w)
    end
    return result
end

이 질문에 대해 매우 유감이지만, 원하는 분할량을 처리할 수 있는 버전을 원하는 사람이 있다면,

-- Split a string into a table using a delimiter and a limit
string.split = function(str, pat, limit)
  local t = {}
  local fpat = "(.-)" .. pat
  local last_end = 1
  local s, e, cap = str:find(fpat, 1)
  while s do
    if s ~= 1 or cap ~= "" then
      table.insert(t, cap)
    end

    last_end = e+1
    s, e, cap = str:find(fpat, last_end)

    if limit ~= nil and limit <= #t then
      break
    end
  end

  if last_end <= #str then
    cap = str:sub(last_end)
    table.insert(t, cap)
  end

  return t
end

"Programming in Lua" 책의 연습 10.1에서 나온 사람들의 경우, 책의 뒷부분에 설명된 개념(반복기)을 사용할 수 없으며 함수는 하나 이상의 문자를 사용해야 한다는 것이 분명합니다.

split()패턴을 원하지 않는 것(분할)과 일치하도록 가져오고 빈 문자열에 빈 테이블을 반환하는 속임수입니다.의 반환plainSplit()다른 언어의 분열에 가깝습니다.

magic = "([%%%.%(%)%+%*%?%[%]%^%$])"

function split(str, sep, plain)
    if plain then sep = string.gsub(sep, magic, "%%%1") end
    
    local N = '\255'
    str = N..str..N
    str = string.gsub(str, sep, N..N)

    local result = {}
    for word in string.gmatch(str, N.."(.-)"..N) do
        if word ~= "" then
            table.insert(result, word)
        end
    end
    return result
end


function plainSplit(str, sep)
    sep = string.gsub(sep, magic, "%%%1")

    local result = {}
    local start = 0
    repeat
        start = start + 1

        local from, to = string.find(str, sep, start)
        from = from and from-1
        
        local word = string.sub(str, start, from, true)
        table.insert(result, word)

        start = to
    until start == nil

    return result
end


function tableToString(t)
    local ret = "{"
    for _, word in ipairs(t) do
        ret = ret .. '"' .. word .. '", '
    end
    ret = string.sub(ret, 1, -3)
    ret = ret .. "}"

    return #ret > 1 and ret or "{}"
end

function runSplit(func, title, str, sep, plain)
    print("\n" .. title)
    print("str: '"..str.."'")
    print("sep: '"..sep.."'")
    local t = func(str, sep, plain)
    print("-- t = " .. tableToString(t))
end



print("\n\n\n=== Pattern split ===")
runSplit(split, "Exercice 10.1", "a whole new world", " ")
runSplit(split, "With trailing seperator", "  a  whole   new world  ", " ")
runSplit(split, "A word seperator", "a whole new world", " whole ")
runSplit(split, "Pattern seperator", "a1whole2new3world", "%d")
runSplit(split, "Magic characters as plain seperator", "a$.%whole$.%new$.%world", "$.%", true)
runSplit(split, "Control seperator", "a\0whole\1new\2world", "%c")
runSplit(split, "ISO Time", "2020-07-10T15:00:00.000", "[T:%-%.]")

runSplit(split, " === [Fails] with \\255 ===", "a\255whole\0new\0world", "\0", true)

runSplit(split, "How does your function handle empty string?", "", " ")



print("\n\n\n=== Plain split ===")
runSplit(plainSplit, "Exercice 10.1", "a whole new world", " ")
runSplit(plainSplit, "With trailing seperator", "  a  whole   new world  ", " ")
runSplit(plainSplit, "A word seperator", "a whole new world", " whole ")
runSplit(plainSplit, "Magic characters as plain seperator", "a$.%whole$.%new$.%world", "$.%")

runSplit(plainSplit, "How does your function handle empty string?", "", " ")

산출량

=== Pattern split ===

Exercice 10.1
str: 'a whole new world'
sep: ' '
-- t = {"a", "whole", "new", "world"}

With trailing seperator
str: '  a  whole   new world  '
sep: ' '
-- t = {"a", "whole", "new", "world"}

A word seperator
str: 'a whole new world'
sep: ' whole '
-- t = {"a", "new world"}

Pattern seperator
str: 'a1whole2new3world'
sep: '%d'
-- t = {"a", "whole", "new", "world"}

Magic characters as plain seperator
str: 'a$.%whole$.%new$.%world'
sep: '$.%'
-- t = {"a", "whole", "new", "world"}

Control seperator
str: 'awholenewworld'
sep: '%c'
-- t = {"a", "whole", "new", "world"}

ISO Time
str: '2020-07-10T15:00:00.000'
sep: '[T:%-%.]'
-- t = {"2020", "07", "10", "15", "00", "00", "000"}

 === [Fails] with \255 ===
str: 'a�wholenewworld'
sep: ''
-- t = {"a"}

How does your function handle empty string?
str: ''
sep: ' '
-- t = {}



=== Plain split ===

Exercice 10.1
str: 'a whole new world'
sep: ' '
-- t = {"a", "whole", "new", "world"}

With trailing seperator
str: '  a  whole   new world  '
sep: ' '
-- t = {"", "", "a", "", "whole", "", "", "new", "world", "", ""}

A word seperator
str: 'a whole new world'
sep: ' whole '
-- t = {"a", "new world"}

Magic characters as plain seperator
str: 'a$.%whole$.%new$.%world'
sep: '$.%'
-- t = {"a", "whole", "new", "world"}

How does your function handle empty string?
str: ''
sep: ' '
-- t = {""}

나는 많은 다른 답변들이 실패한 에지 케이스를 가지고 있다는 것을 발견했습니다(예: 주어진 문자열에 포함된 경우).#,{또는}문자 또는 다음과 같은 구분 기호 문자가 지정된 경우%탈출이 필요함).다음은 제가 대신 사용한 구현입니다.

local function newsplit(delimiter, str)
    assert(type(delimiter) == "string")
    assert(#delimiter > 0, "Must provide non empty delimiter")

    -- Add escape characters if delimiter requires it
    delimiter = delimiter:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0")

    local start_index = 1
    local result = {}

    while true do
       local delimiter_index, _ = str:find(delimiter, start_index)

       if delimiter_index == nil then
          table.insert(result, str:sub(start_index))
          break
       end

       table.insert(result, str:sub(start_index, delimiter_index - 1))

       start_index = delimiter_index + 1
    end

    return result
end

다음은 Lua 4.0에서 작동하는 루틴으로, sep으로 구분입력 문자열의 하위 문자열 테이블을 반환합니다.

function string_split(inputstr, sep)
    local inputstr = inputstr .. sep
    local idx, inc, t = 0, 1, {}
    local idx_prev, substr
    repeat 
        idx_prev = idx
        inputstr = strsub(inputstr, idx + 1, -1)    -- chop off the beginning of the string containing the match last found by strfind (or initially, nothing); keep the rest (or initially, all)
        idx = strfind(inputstr, sep)                -- find the 0-based r_index of the first occurrence of separator 
        if idx == nil then break end                -- quit if nothing's found
        substr = strsub(inputstr, 0, idx)           -- extract the substring occurring before the separator (i.e., data field before the next delimiter)
        substr = gsub(substr, "[%c" .. sep .. " ]", "") -- eliminate control characters, separator and spaces
        t[inc] = substr             -- store the substring (i.e., data field)
        inc = inc + 1               -- iterate to next
    until idx == nil
    return t
end

이 간단한 테스트는

inputstr = "the brown lazy fox jumped over the fat grey hen ... or something."
sep = " " 
t = {}
t = string_split(inputstr,sep)
for i=1,15 do
    print(i, t[i])
end

산출물:

--> t[1]=the
--> t[2]=brown
--> t[3]=lazy
--> t[4]=fox
--> t[5]=jumped
--> t[6]=over
--> t[7]=the
--> t[8]=fat
--> t[9]=grey
--> t[10]=hen
--> t[11]=...
--> t[12]=or
--> t[13]=something.

사용 사례에 따라 유용할 수 있습니다.플래그의 양쪽에 있는 모든 텍스트를 잘라냅니다.

b = "This is a string used for testing"

--Removes unwanted text
c = (b:match("a([^/]+)used"))

print (c)

출력:

string

언급URL : https://stackoverflow.com/questions/1426954/split-string-in-lua