web-dev-qa-db-ja.com

Luaで文字列を分割しますか?

文字列を単純に分割する必要がありますが、この機能はないようで、手動でテストした方法は機能していないようです。どうすればいいですか?

143
RCIX

これが私の本当に簡単な解決策です。 gmatch関数を使用して、目的の区切り文字以外の少なくとも1文字のANYTHINGを含む文字列をキャプチャします。デフォルトでは、区切り文字は任意の空白(Luaでは%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
76
user973713

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

トークンを繰り返し処理するだけの場合、これは非常に適切です。

line = "one, two and 3!"

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

出力:

1、

そして

3!

簡単な説明:「[^%s] +」パターンは、スペース文字間のすべての空でない文字列に一致します。

23
Hugo

string.gmatchが文字列内でpatternsを見つけるように、この関数はbetweenパターンを見つけます:

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

デフォルトでは、空白で区切られたものを返します。

14
Norman Ramsey

関数は次のとおりです。

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

11
Faisal Hanif

私はこの短い解決策が好きです

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

猫の皮を剥ぐ方法は複数あるため、私のアプローチは次のとおりです。

コード

#!/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は、区切り文字が見つかるまですべての文字を受け取ります。

6
Diego Pino

次の方法を使用できます。

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
krsk9999

単に区切り記号の上に座っている

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

これらの回答の多くは、単一文字のセパレータのみを受け入れるか、Edgeのケースをうまく処理しない(たとえば、空のセパレータ)ので、より明確なソリューションを提供すると思いました。

Scribunto MediaWiki extensioncode から採用された2つの関数gsplitsplitは、Wikipediaのようなウィキで使用されます。コードは GPL v2 でライセンスされています。変数名を変更し、コードを少しわかりやすくするためにコメントを追加しました。また、Unicode文字列にScribuntoのパターンの代わりに通常のLua文字列パターンを使用するようにコードを変更しました。元のコードにはテストケースがあります here

-- 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
4
Jack Taylor

上記の例を使用して、独自の関数を作成しました。しかし、私にとって欠けていたのは、魔法のキャラクターを自動的にエスケープすることでした。

これが私の貢献です。

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

他では見られない方法

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

penlight library を使用できます。これには、リストを出力する区切り文字を使用して文字列を分割する機能があります。

Luaでプログラミングや欠落しているときに必要になる可能性のある関数の多くを実装しています。

これを使用するためのサンプルを次に示します。

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

ユースケースによっては、これが役立つ場合があります。フラグの両側のすべてのテキストを切り取ります。

b = "This is a string used for testing"

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

print (c)

出力:

string
0
greenage