如何在Racket中实现以下过程:
(command->string "printf" "hello world")
以这样的方式:
- 它在子流程中运行
argv[]
'("printf" "hello world")
,在PATH
中查找printf
- 如果子进程退出时代码为零,则以字符串形式返回stdout
- 如果子流程退出为非零,则引发异常
- Stdin和stderr被忽略;它们与Racket过程相同
您可以使用
(with-output-to-string
(lambda ()
(or (system* (find-executable-path "printf") "hello world")
(error 'who "command failed"))))
如果您在Racket REPL上尝试此操作,它会起作用,但似乎会混淆REPL,并且不会显示下一个提示。我认为printf
命令可能在窥探stdin,或者XREPL中有一个错误。用包裹上面的表达式
(parameterize ((current-input-port (open-input-string ""))) _)
似乎解决了这个问题。
(define (command->string command . args)
(let-values (((sub stdout stdin stderr)
(apply subprocess #f
(current-input-port)
(current-error-port)
(find-executable-path command)
args)))
(let ((output (port->string stdout)))
(subprocess-wait sub)
(if (eqv? 0 (subprocess-status sub))
output
(error "Command failed:" (cons command args))))))
(writeln (command->string "printf" "%s" "hello world"))
如果Racket的任何人正在阅读,请考虑在标准库中添加这样的内容。这很简单,而且通常需要。