我正在读取 PHP 中的流,使用 proc_open 和 fgets($stdout),试图在它进入时获取每一行。
许多 linux 程序(包管理器、wget、rsync)只使用 CR(回车)字符来表示定期“就地”更新的行,例如下载进度。我想在这些更新发生时立即捕捉它们(作为单独的行)。
目前,fgets($stdout) 只是一直读取直到 LF,所以当进度非常缓慢时(例如大文件)它会一直读取直到完全完成,然后将所有更新的行作为一个返回长字符串,包括 CR。
我已经尝试设置“mac”选项来将 CR 检测为行尾:
ini_set('auto_detect_line_endings',true);
但这似乎行不通。
现在,stream_get_line 允许我将 CR 设置为换行符,但不是将 CRLF、CR 和 LF 都视为分隔符的“包罗万象”解决方案。
我当然可以阅读整行,使用各种 PHP 方法将其拆分并用 LF 替换所有类型的换行符,但它是一个流,我希望 PHP 能够在它仍在运行时获得进度指示。
所以我的问题:
我如何从 STDOUT 管道(从 proc_open)读取直到发生 LF 或 CR,而不必等到整行都进入?
提前致谢!
我使用 Fleshgrinder 的过滤器类将流中的\r 替换为\n(参见接受的答案),并将 fgets() 替换为 fgetc() 以获得对 STDOUT 内容的更多“实时”访问:
$stdout = $proc->pipe(1);
stream_filter_register("EOL", "EOLStreamFilter");
stream_filter_append($stdout, "EOL");
while (($o = fgetc($stdout))!== false){
$out .= $o; // buffer the characters into line, until \n.
if ($o == "\n"){echo $out;$out='';} // can now easily wrap the $out lines in JSON
}
最佳答案
在使用流之前使用流过滤器规范化换行符。我根据 stream_filter_register 上的 PHP 手册页中的示例创建了以下代码来完成此操作。 .
<?php
// https://php.net/php-user-filter
final class EOLStreamFilter extends php_user_filter {
public function filter($in, $out, &$consumed, $closing)
{
while ($bucket = stream_bucket_make_writeable($in)) {
$bucket->data = str_replace([ "\r\n", "\r" ], "\n", $bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
stream_filter_register("EOL", "EOLStreamFilter");
// Open stream …
stream_filter_append($yourStreamHandle, "EOL");
// Perform your work with normalized EOLs …
编辑: Mark Baker 对您的问题发表的评论是真实的。大多数 Linux 发行版都为 STDOUT 使用行缓冲区,Apple 可能也在做同样的事情。另一方面,大多数 STDERR 流都是无缓冲的。您可以尝试将程序的输出重定向到另一个管道(例如 STDERR 或任何其他管道),看看您是否更幸运。
关于PHP:试图让 fgets() 在 CRLF、CR 和 LF 上触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27907913/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
我有一个rubyonrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我想写一点“Deprecate-It”库并经常使用“method_added”回调。但是现在我注意到在包含模块时不会触发此回调。是否有任何回调或变通方法,以便在某些内容包含到自身时通知类“Foobar”?用于演示的小Demo:#IncludingModulswon'ttriggermethod_addedcallbackmoduleInvisibleMethoddefinvisible"Youwon'tgetacallbackfromme"endendclassFoobardefself.method_added(m)puts"InstanceMethod:'#{m}'addedto'
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它
我不是Ruby专家,但想弄清楚发生了什么,因为我试图让指南针在节点应用程序中工作,但我的Ruby似乎坏了。打字:ruby--version让我:ruby2.1.1p76(2014-02-24revision45161)[x86_64-darwin13.0]我安装了Homebrew,之前遇到过Ruby版本的问题,但它似乎已安装并且可以正常工作。但是,当我使用gem输入请求时,出现此错误:$gem-hErrorloadingRubyGemsplugin"/Users/user_dir/.rvm/gems/ruby-2.1.1@global/gems/executable-hooks-1.3
我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文
我刚刚发现String#split有以下奇怪的行为:"a\tbc\nd".split=>["a","b","c","d"]"a\tbc\nd".split('')=>["a","b","c","d"]"a\tbc\nd".split(//)=>["a\tb","c\nd"]Thesource(来自2.0.0的string.c)超过200行,包含这样一段话:/*L5909*/elseif(rb_enc_asciicompat(enc2)==1){if(RSTRING_LEN(spat)==1&&RSTRING_PTR(spat)[0]==''){split_type=awk;}}后来,在
以下代码使用了触发器运算符。(1..10).each{|x|print"#{x},"ifx==3..x==5}为什么结果是3,4,5?我觉得应该是3,4。如教程中所述,此表达式在x==3时为真,并一直为真,直到x==5。如果“5”的计算结果为false,如何打印它?谁能为我澄清一下? 最佳答案 来自“TheRubyProgrammingLanguage”的重要链接是:4.6.9.1Booleanflip-flopsWhenthe..and...operatorsareusedinaconditional,suchasanifstat