루아에서 스플릿 스트링?


160

간단한 문자열 분할을 수행해야하지만이 기능이없는 것 같으며 테스트 한 수동 방법이 작동하지 않는 것 같습니다. 어떻게합니까?


참조하시기 바랍니다 분할 문자열
앤드류 헤어

답변:


96

여기 정말 간단한 해결책이 있습니다. 적어도 포함 캡처 문자열에 gmatch 기능을 사용하여 하나 개 의 문자 아무것도 원하는 구분 이외. 구분 기호는 기본적으로 ** 모든 * 공백 (루아에서 % s)입니다.

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

.


1
감사. 그냥 내가 무엇을 찾고 있었다.
Nicholas

3
와우,이 전체 질문의 첫 번째 대답은 실제로 테이블을 반환하는 함수를 가지고 있습니다. 그러나 t와 나는 "local"수정자가 필요합니다. 왜냐하면 전역을 덮어 쓰고 있기 때문입니다. :)
cib

3
다른 사람들이 지적했듯이 t [i] = str 대신 table.insert (t, str)을 사용하여 이것을 단순화 할 수 있으며 i = 1 또는 i = i +1이 필요하지 않습니다
James Newton

2
문자열에 빈 값이 포함 된 경우 작동하지 않습니다 (예 : 'foo,,bar'. 당신은 얻을 {'foo','bar'}대신{'foo', '', 'bar'}
안드라스

5
맞습니다. 이 경우 다음 버전이 작동합니다. function split(inputstr, sep) sep=sep or '%s' local t={} for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do table.insert(t,field) if s=="" then return t end end end
bart

33

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

Lua 5.1 Reference Manual의 string.gmatch () 사용 예 :

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

어쨌든 그 루아 사용자 페이지 감사에서 구현을 "빌린"
RCIX

24

토큰을 반복하고 싶다면 아주 깔끔합니다.

line = "one, two and 3!"

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

산출:

하나,

삼!

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


2
패턴은 %S, 당신이 언급 한 것과 같다 %S의 부정이 %s같은 %D의 부정이다 %d. 또한 %w동일합니다 [A-Za-z0-9_](로케일에 따라 다른 문자가 지원 될 수 있음).
Lars Gyrup Brink Nielsen

14

문자열에서 패턴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

기본적으로 공백으로 구분 된 것을 반환합니다.


6
+1. 다른 Lua 초보자에게 참고 : 반복자를 반환하며 '패턴 사이'에는 문자열의 시작과 끝이 포함됩니다. (초보자로서 나는 이것을 이해하기 위해 노력해야했다.)
다리우스 베이컨

12

기능은 다음과 같습니다.

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/SplitJoin


7

나는이 짧은 해결책을 좋아한다

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

너무 짧고 단순하기 때문에 이것이 내가 가장 좋아하는 것입니다. 어떤 일이 일어나는지 잘 모르겠습니다. 누군가 나에게 설명 할 수 있습니까?
육각형

2
점을 구분 기호 (또는 잠재적으로 다른 패턴의 마술 문자)로 사용할 때 실패
TurboHz

6

고양이를 껍질을 벗기는 방법은 여러 가지가 있으므로 여기에 내 접근 방식이 있습니다.

코드 :

#!/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이 구분을 찾을 때까지 모든 문자를합니다.


5

이 방법을 사용할 수 있습니다 :

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) 

5

이러한 답변 중 많은 부분이 단일 문자 구분 기호 만 허용하거나 가장자리 사례를 잘 처리하지 못합니다 (예 : 빈 구분 기호).보다 확실한 솔루션을 제공 할 것이라고 생각했습니다.

여기서 두 개의 함수이다 gsplit하고 split로부터 적응 부호Scribunto 위키 확장 위키 위키 등에 사용된다. 이 코드는 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

5

다른 사람에게는 보이지 않는 방법

function str_split(str, sep)
    if sep == nil then
        sep = '%s'
    end 

    local res = {}
    local func = function(w)
        table.insert(res, w)
    end 

    string.gsub(str, '[^'..sep..']+', func)
    return res 
end

4

단순히 구분 기호에 앉아

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

3

위의 예제를 사용하여 자체 기능을 만들었습니다. 그러나 나를 위해 빠진 조각은 자동으로 마술 캐릭터를 탈출했습니다.

여기 내 공헌이 있습니다 :

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

이것은 나의 큰 문제이기도했다. 이것은 마법 캐릭터, 멋진 캐릭터와 잘 작동합니다
Andrew White

1

펜 라이트 라이브러리를 사용할 수 있습니다 . 리스트를 출력하는 구분자를 사용하여 문자열을 분할하는 기능이 있습니다.

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

다음은이를 사용하기위한 샘플입니다.

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

0

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

b = "This is a string used for testing"

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

print (c)

산출:

string

0

이 질문에 늦었지만 누군가가 원하는 스플릿 양을 처리하는 버전을 원한다면 .....

-- 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

0

루아에서 프로그래밍하면 운이 좋지 않습니다. 루아 (Lua)는 저자들이 표준 라이브러리에서 "분할"기능을 구현 한 적이 없기 때문에 악명 높게 악명 높은 것으로 알려진 프로그래밍 언어 중 하나입니다. 거의 모든 사람에게 효과적이지만 코너 케이스를 깨뜨릴 수있는 많은 반 작업 예제가 산재 합니다 . 이것은 Lua의 최첨단 기술이며 Lua에서 프로그램하는 모든 사람들은 단순히 치아를 움켜 쥐고 캐릭터를 반복합니다. 때로는 더 나은 솔루션이 많이 있지만 확실하게 더 나은 솔루션은 거의 없습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.