热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何用lua构造一个读写管道?-Howdoyouconstructaread-writepipewithlua?

Idliketodotheequivalentof:我想做的是foo$(echo$foo|someprogram)withinlua--ie,Ivegot

I'd like to do the equivalent of:

我想做的是

foo=$(echo "$foo"|someprogram)

within lua -- ie, I've got a variable containing a bunch of text, and I'd like to run it through a filter (implemented in python as it happens).

在lua中——也就是说,我有一个包含大量文本的变量,我想通过一个过滤器来运行它(在python中实现)。

Any hints?

有提示吗?

Added: would really like to do this without using a temporary file

添加:在不使用临时文件的情况下真的愿意这样做。

7 个解决方案

#1


4  

There is nothing in the Lua standard library to allow this.

在Lua标准库中没有任何东西允许这样做。

Here is an in-depth exploration of the difficulties of doing bidirectional communication properly, and a proposed solution:

下面是对双向沟通困难的深入探讨,并提出了解决方案:

if possible, redirect one end of the stream (input or output) to a file. I.e.:

如果可能,将流的一端(输入或输出)重定向到一个文件。例如:

fp = io.popen("foo >/tmp/unique", "w")
fp:write(anything)
fp:close()
fp = io.open("/tmp/unique")
x = read("*a")
fp:close()

You may be interested in this extension which adds functions to the os and io namespaces to make bidirectional communication with a subprocess possible.

您可能会对这个扩展感兴趣,它将函数添加到操作系统和io名称空间中,以使双向通信成为可能。

#2


3  

Aha, a possibly better solution:

啊哈,一个更好的解决方案:

require('posix')
require('os')
require('io')

function splat_popen(data,cmd)
   rd,wr = posix.pipe()
   io.flush()
   child = posix.fork()
   if child == 0 then
      rd:close()
      wr:write(data)
      io.flush()
      os.exit(1)
   end
   wr:close()

   rd2,wr2 = posix.pipe()
   io.flush()
   child2 = posix.fork()
   if child2 == 0 then
      rd2:close()
      posix.dup(rd,io.stdin)
      posix.dup(wr2,io.stdout)
      posix.exec(cmd)
      os.exit(2)
   end
   wr2:close()
   rd:close()

   y = rd2:read("*a")
   rd2:close()

   posix.wait(child2)
   posix.wait(child)

   return y
end

munged=splat_popen("hello, world","/usr/games/rot13")
print("munged: "..munged.." !")

#3


3  

As long as your Lua supports io.popen, this problem is easy. The solution is exactly as you have outlined, except instead of $(...) you need a function like this one:

只要你的Lua支持io。popen,这个问题很简单。解决方案与您所描述的完全一样,除了$(…)您需要一个这样的函数:

function os.capture(cmd, raw)
  local f = assert(io.popen(cmd, 'r'))
  local s = assert(f:read('*a'))
  f:close()
  if raw then return s end
  s = string.gsub(s, '^%s+', '')
  s = string.gsub(s, '%s+$', '')
  s = string.gsub(s, '[\n\r]+', ' ')
  return s
end

You can then call

你可以叫

local foo = ...
local cmd = ("echo $foo | someprogram"):gsub('$foo', foo)
foo = os.capture(cmd)

I do stuff like this all the time. Here's a related useful function for forming commands:

我一直都是这样做的。这是一个有关形成命令的有用函数:

local quote_me = '[^%w%+%-%=%@%_%/]' -- complement (needn't quote)
local strfind = string.find

function os.quote(s)
  if strfind(s, quote_me) or s == '' then
    return "'" .. string.gsub(s, "'", [['"'"']]) .. "'"
  else
    return s
  end
end

#4


2  

I stumbled on this post while trying to do the same thing and never found a good solution, see the code below for how I solved my issues. This implementation allows users to access stdin, stdout, stderr and get the return status code. A simple wrapper is called for simple pipe calls.

我在试图做同样的事情时无意中发现了这篇文章,并且从来没有找到一个好的解决方案,看看下面的代码如何解决我的问题。这个实现允许用户访问stdin、stdout、stderr并获得返回状态代码。一个简单的包装器需要简单的管道调用。

require("posix")

--
-- Simple popen3() implementation
--
function popen3(path, ...)
    local r1, w1 = posix.pipe()
    local r2, w2 = posix.pipe()
    local r3, w3 = posix.pipe()

    assert((w1 ~= nil or r2 ~= nil or r3 ~= nil), "pipe() failed")

    local pid, err = posix.fork()
    assert(pid ~= nil, "fork() failed")
    if pid == 0 then
        posix.close(w1)
        posix.close(r2)
        posix.dup2(r1, posix.fileno(io.stdin))
        posix.dup2(w2, posix.fileno(io.stdout))
        posix.dup2(w3, posix.fileno(io.stderr))
        posix.close(r1)
        posix.close(w2)
        posix.close(w3)

        local ret, err = posix.execp(path, unpack({...}))
        assert(ret ~= nil, "execp() failed")

        posix._exit(1)
        return
    end

    posix.close(r1)
    posix.close(w2)
    posix.close(w3)

    return pid, w1, r2, r3
end

--
-- Pipe input into cmd + optional arguments and wait for completion
-- and then return status code, stdout and stderr from cmd.
--
function pipe_simple(input, cmd, ...)
    --
    -- Launch child process
    --
    local pid, w, r, e = popen3(cmd, unpack({...}))
    assert(pid ~= nil, "filter() unable to popen3()")

    --
    -- Write to popen3's stdin, important to close it as some (most?) proccess
    -- block until the stdin pipe is closed
    --
    posix.write(w, input)
    posix.close(w)

    local bufsize = 4096
    --
    -- Read popen3's stdout via Posix file handle
    --
    local stdout = {}
    local i = 1
    while true do
        buf = posix.read(r, bufsize)
        if buf == nil or #buf == 0 then break end
        stdout[i] = buf
        i = i + 1
    end

    --
    -- Read popen3's stderr via Posix file handle
    --
    local stderr = {}
    local i = 1
    while true do
        buf = posix.read(e, bufsize)
        if buf == nil or #buf == 0 then break end
        stderr[i] = buf
        i = i + 1
    end

    --
    -- Clean-up child (no zombies) and get return status
    --
    local wait_pid, wait_cause, wait_status = posix.wait(pid)

    return wait_status, table.concat(stdout), table.concat(stderr)
end

--
-- Example usage
--
local my_in = io.stdin:read("*all")
--local my_cmd = "wc"
--local my_args = {"-l"}
local my_cmd = "spamc"
local my_args = {} -- no arguments
local my_status, my_out, my_err = pipe_simple(my_in, my_cmd, unpack(my_args))

-- Obviously not interleaved as they would have been if printed in realtime
io.stdout:write(my_out)
io.stderr:write(my_err)

os.exit(my_status)

#5


0  

Here is how I solved the problem, it require lua posix.

这里是我如何解决这个问题,它需要lua posix。

          p = require 'posix'
          local r,w = p.pipe()
          local r1,w1 = p.pipe()
          local cpid = p.fork()
          if cpid == 0 then -- child reads from pipe                                     
             w:close()
             r1:close()
             p.dup(r, io.stdin)
             p.dup(w1 ,io.stdout)
             p.exec('./myProgram')
             r:close()
             w1:close()
             p._exit(0)
          else -- parent writes to pipe                                                  
             IN = r1
             OUT = w
          end

During myProgram execution, you'l read and write from normal io and after this part of code you just have to write/read on IN and OUT to comunicate with child program.

在myProgram执行过程中,您将从正常的io中读取和写入,在这段代码之后,您只需要在与子程序的通信中读写。

#6


0  

It's easy, no extensions necessary (tested with lua 5.3).

这很简单,没有必要的扩展(用lua 5.3测试)。

#!/usr/bin/lua
-- use always locals
local stdin = io.stdin:lines()
local stdout = io.write

for line in stdin do
    stdout (line)
end 

save as inout.lua and do chmod +x /tmp/inout.lua

存inout。lua和do chmod +x /tmp/inout.lua。

20:30 $ foo=$(echo "bla"|  /tmp/inout.lua)
20:30 $ echo $foo
bla

#7


-1  

A not very nice solution that avoids a temporary file...

一个不太好的解决方案,避免了一个临时文件…

require("io")
require("posix")

x="hello\nworld"

posix.setenv("LUA_X",x)
i=popen('echo "$LUA_X" | myfilter')
x=i.read("*a")

推荐阅读
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • Openresty+Lua+Redis灰度发布
    Openresty+Lua+Redis灰度发布灰度发布,简单来说,就是根据各种条件,让一部分用户使用旧版本,另一部分用户使用新版本。百度百科中解释:灰度发布是指在黑与白之间,能够平 ... [详细]
  • 整整的花了一个下午的时候,才在lua中调用了动态链接库。比起其他脚本语言,lua的调用方式算是比较繁琐的,但是lua的编程思想非常的统一& ... [详细]
  • luarestyqlesswebUI界面运行
    lua-resty-qless-web是lua-resty-qless的web管理界面以及lua-resty-template模版引擎开发的,里面实现了一个简单的路由功能备注:de ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • java实现rstp格式转换使用ffmpeg实现linux命令第一步安装node.js和ffmpeg第二步搭建node.js启动websocket接收服务
    java实现rstp格式转换使用ffmpeg实现linux命令第一步安装node.js和ffmpeg第二步搭建node.js启动websocket接收服务第三步java实现 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • python3 logging
    python3logginghttps:docs.python.org3.5librarylogging.html,先3.5是因为我当前的python版本是3.5之所 ... [详细]
  • 爬虫框架Scrapy(三)
    正文共:2957字6图预计阅读时间:8分钟每日分享Bethetypeofpersonyouwanttomeet.努力变成理想的模样。小闫笔记࿱ ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了redis调优的实战经验相关的知识,希望对你有一定的参考价值。本文根据redis的inf ... [详细]
  • 南京拓界诚聘linux C/C++、Windows开发工程师等
      南京拓界信息技术有限公司诚聘linuxC/C++,Windows逆向工程师、Windows系统工程师、Windows驱动工程师,一年以上经验,南京地区,非外包公司,五险一金,福利齐全, ... [详细]
author-avatar
阵风阿斯顿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有