Используйте переменные внутри строки в lua - PullRequest
1 голос
/ 23 сентября 2019

В javascript мы можем сделать следующее:

var someString = `some ${myVar} string`

У меня есть следующий код lua, myVar - это число, которое должно быть в квадратных скобках:

splash:evaljs('document.querySelectorAll("a[title*=further]")[myVar]')

Ответы [ 2 ]

2 голосов
/ 23 сентября 2019

Функция, которая соответствует вашему описанию: string.format:

splash:evaljs(string.format('document.querySelectorAll("a[title*=further]")[%s]', myVar))

Она не такая многословная, как ${}.Это скорее старый добрый (и ненавистный) sprintf.

0 голосов
/ 24 сентября 2019

Я написал эмуляцию строк f'' Python, представляющих собой набор функций, которые можно скрыть в файле require.Так что, если вам нравятся строки f'' Python, это может быть то, что вы ищете.

(Если кто-то обнаружит ошибки, пожалуйста, сообщите.)

Это довольно большой по сравнению с другимирешение, но если вы скрываете большую часть в библиотеке, то ее использование становится более компактным и читаемым, IMO.

С этой библиотекой вы можете делать следующее, например:

require 'f_strings'
a = 12345
print(f'Number: {a}, formatted with two decimals: {a::%.2f}')
-- Number: 12345, formatted with two decimals: 12345.00

Обратите внимание на использование кодов форматирования Lua string.format и использование двойного двоеточия (вместо двоеточия Python) для спецификаторов формата из-за использования двоеточия Lua для методов.

Я извлек только соответствующие функции избольшая библиотека.Хотя некоторые оптимизации могут быть возможны для этого конкретного случая использования, я оставляю их без изменений, поскольку они являются универсальными и могут также быть полезными для других целей.

А вот необходимая библиотека (размещенная где-то в вашей папке библиотек Lua):

-- f_strings.lua ---
unpack = table.unpack or unpack

--------------------------------------------------------------------------------
-- Escape special pattern characters in string to be treated as simple characters
--------------------------------------------------------------------------------

local
function escape_magic(s)
  local MAGIC_CHARS_SET = '[()%%.[^$%]*+%-?]'
  if s == nil then return end
  return (s:gsub(MAGIC_CHARS_SET,'%%%1'))
end

--------------------------------------------------------------------------------
-- Returns iterator to split string on given delimiter (multi-space by default)
--------------------------------------------------------------------------------

function string:gsplit(delimiter)
  if delimiter == nil then return self:gmatch '%S+' end --default delimiter is any number of spaces
  if delimiter == '' then return self:gmatch '.' end
  if type(delimiter) == 'number' then   --break string in equal-size chunks
    local index = 1
    local ans
    return function()
             ans = self:sub(index,index+delimiter-1)
             if ans ~= '' then
               index = index + delimiter
               return ans
             end
           end
  end
  if self:sub(-#delimiter) ~= delimiter then self = self .. delimiter end
  return self:gmatch('(.-)'..escape_magic(delimiter))
end

--------------------------------------------------------------------------------
-- Split a string on the given delimiter (comma by default)
--------------------------------------------------------------------------------

function string:split(delimiter,tabled)
  tabled = tabled or false              --default is unpacked
  local ans = {}
  for item in self:gsplit(delimiter) do
    ans[#ans+1] = item
  end
  if tabled then return ans end
  return unpack(ans)
end

--------------------------------------------------------------------------------

function copy(t)              --returns a simple (shallow) copy of the table
  if type(t) == 'table' then
    local ans = {}
    for k,v in next,t do ans[ k ] = v end
    return ans
  end
  return t
end

--------------------------------------------------------------------------------

function eval(expr,vars)
  --evaluate a string expression with optional variables
  if expr == nil then return end
  vars = vars or {}
  assert(type(expr) == 'string','String expected as 1st arg')
  assert(type(vars) == 'table','Variable table expected as 2nd arg')
  local env = {abs=math.abs,acos=math.acos,asin=math.asin,atan=math.atan,
               atan2=math.atan2,ceil=math.ceil,cos=math.cos,cosh=math.cosh,
               deg=math.deg,exp=math.exp,floor=math.floor,fmod=math.fmod,
               frexp=math.frexp,huge=math.huge,ldexp=math.ldexp,log=math.log,
               max=math.max,min=math.min,modf=math.modf,pi=math.pi,pow=math.pow,
               rad=math.rad,random=math.random,randomseed=math.randomseed,
               sin=math.sin,sinh=math.sinh,sqrt=math.sqrt,tan=math.tan,
               tanh=math.tanh}
  for name,value in pairs(vars) do env[name] = value end
  local a,b = pcall(load('return '..expr,nil,'t',env))
  if a == false then return nil,b else return b end
end

--------------------------------------------------------------------------------
-- f'' formatted strings like those introduced in Python v3.6
-- However, you must use Lua style format modifiers as with string.format()
--------------------------------------------------------------------------------

function f(s)
  local env = copy(_ENV)                --start with all globals
  local i,k,v,fmt = 0
  repeat
    i = i + 1
    k,v = debug.getlocal(2,i)           --two levels up (1 level is this repeat block)
    if k ~= nil then env[k] = v end
  until k == nil
  local
  function go(s)
    local fmt
    s,fmt = s:sub(2,-2):split('::')
    if s:match '%b{}' then s = (s:gsub('%b{}',go)) end
    s = eval(s,env)
    if fmt ~= nil then
      if fmt:match '%b{}' then fmt = eval(fmt:sub(2,-2),env) end
      s = fmt:format(s)
    end
    return s
  end
  return (s:gsub('%b{}',go))
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...