英文:
Interactive process with Kotlin
问题
以下是您要的翻译内容:
I'm trying to interact with sh
. This is the easiest case I want to resolve.
我正在尝试与 sh
交互。这是我想解决的最简单的情况。
The most easy is:
最简单的情况是:
typealias ExitStatus = Int
fun executeIO(cmd: List<String>): ExitStatus =
ProcessBuilder(cmd).inheritIO().start().waitFor()
But the Kotlin code doesn't have any control when the sh
are executing.
但是 Kotlin 代码在 sh
执行时没有任何控制。
When you know how many times you want to write
当您知道要写多少次时:
fun executeNTimes(cmd: List<String>, times: Int) = runBlocking {
val process = ProcessBuilder(cmd)
.start()
launch { process.errorStream.bufferedReader().useLines { seq -> seq.toList().forEach { println("stderr: $it") } } }
launch { process.inputStream.bufferedReader().useLines { seq -> seq.toList().forEach { println("stdout: $it") } } }
OutputStreamWriter(process.outputStream, "UTF-8").use { w ->
repeat(times) {
readln().let { println("input: $it"); w.write(it) }
w.appendLine()
w.flush()
}
}
process.waitFor()
}
But that is not interactive!
但这并不是交互式的!
> cmd = sh and times = 2:
> cmd = sh,times = 2:
echo exit on stdout
input: echo exit on stdout
echo exit on stderr 1>&2
input: echo exit on stderr 1>&2
stderr: exit on stderr
stdout: exit on stdout
Is not interactive because needs to close the buffer for starting to work.
这不是交互式的,因为需要关闭缓冲区才能开始工作。
My expectation for an interactive process is the next one:
我的期望是进行交互式处理:
input: echo exit on stdout
stdout: exit on stdout
input: echo exit on stderr 1>&2
stderr: exit on stderr
input: exit
How can I do that?
我该如何实现这一点?
英文:
I'm trying to interact with sh
. This is the easiest case I want to resolve.
The most easy is:
typealias ExitStatus = Int
fun executeIO(cmd: List<String>): ExitStatus =
ProcessBuilder(cmd).inheritIO().start().waitFor()
But the Kotlin code doesn't have any control when the sh
are executing.
When you know how many times you want to write
fun executeNTimes(cmd: List<String>, times: Int) = runBlocking {
val process = ProcessBuilder(cmd)
.start()
launch { process.errorStream.bufferedReader().useLines { seq -> seq.toList().forEach { println("stderr: $it") } } }
launch { process.inputStream.bufferedReader().useLines { seq -> seq.toList().forEach { println("stdout: $it") } } }
OutputStreamWriter(process.outputStream, "UTF-8").use { w ->
repeat(times) {
readln().let { println("input: $it"); w.write(it) }
w.appendLine()
w.flush()
}
}
process.waitFor()
}
But that is not interactive!
> cmd = sh and times = 2:
echo exit on stdout
input: echo exit on stdout
echo exit on stderr 1>&2
input: echo exit on stderr 1>&2
stderr: exit on stderr
stdout: exit on stdout
Is not interactive because needs to close the buffer for starting to work.
My expectation for interactive process is the next one:
input: echo exit on stdout
stdout: exit on stdout
input: echo exit on stderr 1>&2
stderr: exit on stderr
input: exit
How I can do that?
答案1
得分: 0
以下是您要的翻译部分:
"After read:
The code has:
fun executeExpect() {
val process = ProcessBuilder(listOf("sh")).start()
val expect = ExpectBuilder()
.withInputs(process.inputStream, process.errorStream)
.withOutput(process.outputStream)
.build()
fun send(str: String) {
expect.sendLine(str)
println("input: $str")
}
"echo exit on stdout".let(::send)
expect.expect(regexp("\n$")).before.let { println("stdout: $it") }
"echo exit on stderr 1>&2".let(::send)
expect.expectIn(1, regexp("\n$")).before.let { println("stderr: $it") }
"exit".let(::send)
expect.expect(eof());
process.waitFor()
expect.close()
}
And now the output is:
input: echo exit on stdout
stdout: exit on stdout
input: echo exit on stderr 1>&2
stderr: exit on stderr
input: exit
```"
<details>
<summary>英文:</summary>
After read:
- https://github.com/agavrilov76/ExpectIt
- https://github.com/agavrilov76/ExpectIt/blob/master/expectit-core/src/test/java/net/sf/expectit/ProcessExample.java
- https://en.wikipedia.org/wiki/Expect
The code has:
```kotlin
fun executeExpect() {
val process = ProcessBuilder(listOf("sh")).start()
val expect = ExpectBuilder()
.withInputs(process.inputStream, process.errorStream)
.withOutput(process.outputStream)
.build()
fun send(str: String) {
expect.sendLine(str)
println("input: $str")
}
"echo exit on stdout".let(::send)
expect.expect(regexp("\n$")).before.let { println("stdout: $it") }
"echo exit on stderr 1>&2".let(::send)
expect.expectIn(1, regexp("\n$")).before.let { println("stderr: $it") }
"exit".let(::send)
expect.expect(eof());
process.waitFor()
expect.close()
}
And now the output is:
input: echo exit on stdout
stdout: exit on stdout
input: echo exit on stderr 1>&2
stderr: exit on stderr
input: exit
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论