windows 运行输入的可执行文件并将输出重定向到txt文件

6qftjkof  于 2023-11-21  发布在  Windows
关注(0)|答案(1)|浏览(214)

我试图将. exe文件的结果重定向到.txt文件中,但我在windows cmd中使用的命令

  1. test.ext < input.txt > output.txt

字符串
didn not correctly show what input file input:

  1. Enter top, an integer between 3 and 29 (including): Enter side, an integer between 2 and 20 (including): Enter 0 for left-tilt or 1 for right-tilt of the side:
  2. ###
  3. #@#
  4. #@#
  5. ###
  6. The number of characters on the perimeter: 10.
  7. The number of characters in the interior: 2.
  8. The number of characters of the parallelogram: 12.


在我的预期中,输出应该是这样的:

  1. Enter top, an integer between 3 and 29 (including): 3
  2. Enter side, an integer between 2 and 20 (including): 2
  3. Enter 0 for left-tilt or 1 for right-tilt of the side: 0
  4. ###
  5. #@#
  6. #@#
  7. ###
  8. The number of characters on the perimeter: 10.
  9. The number of characters in the interior: 2.
  10. The number of characters of the parallelogram: 12.


就像.exe文件显示我当我运行它。
有没有简单的方法来实现我想要的?

dsekswqp

dsekswqp1#

tl;dr

  • 行为归结为给定的可执行文件选择如何处理(默认情况下)* 交互式提示 *,特别是当它们的响应通过 * 标准输入 *(例如通过<重定向或通过管道输入(|))而不是通过 * 用户交互输入 * 提供时。
  • 结果是,获得不同行为的唯一方法是 * 修改可执行文件 *。
    两个方面发挥作用:
  • 一个交互式提示符的 message 是写到 stdout 还是直接写到终端 *,以及如果stdin被重定向,即如果响应将从stdin读取,是否打印消息 *。
  • 提示符的 * 响应 * 是否写入到 stdout,或者 * 直接写入到终端 *,或者 * 根本不写入 (如果响应是通过 * stdin 提供的)。
  • 理想情况下 *,如果stdin被重定向 *,您希望给定的可执行文件选择以下组合之一,基于以下设计选择:
    ***(a)*如果(默认情况下)交互式提示被认为是一个纯粹的交互式功能,与应用程序的(stdout) 输出 * 无关:
    • 既不打印 * 提示消息,也不打印从标准输入读取的值。
      ***(B)**如果应用程序希望生成更像交互式会话的 * 抄本 * 的输出,同时显示提示消息和响应:
  • 将提示消息和值从stdin * 打印到 stdout

不幸的是,您的可执行文件没有使用任何方法,并做出以下选择组合:

  • 它将提示消息写入stdout,而不打印(stdin提供的)响应
  • 由于提示消息本身没有尾随的换行符-假定响应应该在同一行上输入 * -没有打印响应(其中 * 确实 * 涉及尾随的换行符)意味着所有(连续的)提示消息出现在同一行上。

例如,* 批处理文件 * 会显示此行为**,您可以使用以下示例批处理文件进行验证:

  1. @echo off
  2. set /P V1="Prompt 1: "
  3. set /P V2="Prompt 2: "
  4. set /P V3="Prompt 3: "
  5. echo Values provided: [%V1%] [%V2%] [%V3%]

字符串
标记为sample.cmd < input.txt > output.txtinput.txt中有3行输入,包含abc,您将在output.txt中看到以下输出:

  1. Prompt 1: Prompt 2: Prompt 3: Values provided: [a] [b] [c]


也就是说,提示消息在没有换行符的情况下连接在一起,并且缺少响应。

PowerShell的 * 行为是特定于平台的,但a(b)解决方案是可能的任何一种方式
重要:以下内容仅适用于从 * 外部 * 通过其 CLIpowershell.exe用于Windows PowerShell,pwsh用于PowerShell(Core)7+)调用PowerShell代码,因为只有这样Read-Host才会从 * 重定向的stdin
读取响应。因此,在类似 Unix 的平台上,它也适用于通过shebang行在PowerShell中实现的可直接执行的shell脚本。

  • 在 * 类Unix* 平台**上,您可以通过常规的Read-Host调用获得所需的行为(b),如以下示例代码所示:
  1. $values =
  2. 1..3 | ForEach-Object {
  3. Read-Host -Prompt "Prompt ${_}"
  4. }
  5. "Values provided: $($values.ForEach({ "[$_]" }))"

  • 不幸的是,在Windows上,提示消息 * 直接打印到控制台 *,因此 * 不是 * 通过标准输出重定向(>)捕获的;解决方法是 * 单独 * 打印提示消息,使用Write-Host及其-NoNewLine开关:
  1. $values =
  2. 1..3 | ForEach-Object {
  3. Write-Host -NoNewLine "Prompt ${_}: "
  4. Read-Host
  5. }
  6. "Values provided: $($values.ForEach({ "[$_]" }))"


比如说,从cmd.exe转换为powershell -ExecutionPolicy Bypass -File sample.ps1 < input.txt > output.txt,在input.txt中有3行输入,包含abc,你会在output.txt中看到以下输出:

  1. Prompt 1: a
  2. Prompt 2: b
  3. Prompt 3: c
  4. Values provided: [a] [b] [c]


也就是说,这相当于行为(b):提示消息和stdin提供的响应都被打印到stdout[1],因此通过>捕获。

PowerShell还支持(a)解决方案,但需要额外的努力:

  1. $values =
  2. 1..3 | ForEach-Object {
  3. # Print the prompt message only if stdin isn't redirected.
  4. if (-not [Console]::IsInputRedirected) {
  5. Write-Host -NoNewline "Prompt ${_}: "
  6. }
  7. # Use the [Console]::ReadLine() rather than Read-Host,
  8. # which *doesn't* echo a stdin-provided response.
  9. [Console]::ReadLine()
  10. }
  11. "Values provided: $($values.ForEach({ "[$_]" }))"


使用与上面相同的示例调用,您现在可以得到:

  1. Values provided: [a] [b] [c]


也就是说,这相当于行为(a):由于stdin重定向(<),提示消息和stdin提供的响应都没有被打印,因此不是>捕获的一部分。
注意事项:

  • 由于PowerShell是基于.NET构建的,这意味着编译后的.NET控制台应用程序可以实现相同的行为,如以下C#示例所示。
    C#实现(a)
  1. using System;
  2. static class Program {
  3. public static int Main(string[] args) {
  4. bool isStdInRedirected = Console.IsInputRedirected;
  5. int promptCount = 3;
  6. string[] values = new string[promptCount];
  7. for (int i = 1; i <= promptCount; ++i)
  8. {
  9. Console.Write(String.Format("Prompt {0}: ", i));
  10. values[i-1] = Console.ReadLine();
  11. if (isStdInRedirected) Console.WriteLine(values[i-1]);
  12. }
  13. Console.Write("Values provided:");
  14. for (int i = 1; i <= promptCount; ++i)
  15. {
  16. Console.Write(String.Format(" [{0}]", values[i-1]));
  17. }
  18. Console.WriteLine();
  19. return 0;
  20. }
  21. }

(B)的C#实现

  1. static class Program {
  2. public static int Main(string[] args) {
  3. bool isStdInRedirected = Console.IsInputRedirected;
  4. int promptCount = 3;
  5. string[] values = new string[promptCount];
  6. for (int i = 1; i <= promptCount; ++i)
  7. {
  8. if (!isStdInRedirected) Console.Write(String.Format("Prompt {0}: ", i));
  9. values[i-1] = Console.ReadLine();
  10. }
  11. Console.Write("Values provided:");
  12. for (int i = 1; i <= promptCount; ++i)
  13. {
  14. Console.Write(String.Format(" [{0}]", values[i-1]));
  15. }
  16. Console.WriteLine();
  17. return 0;
  18. }
  19. }


[1]也许令人惊讶的是,Write-Host也打印到标准输出,即使PowerShell-* 内部 * 它被设计为 * 绕过 * PowerShell的类似 * 成功 * output stream
事实上-不幸的是-默认情况下,PowerShell的所有 *(六个!)输出流都Map到外部调用者看到的标准输出流-参见GitHub issue #7989

展开查看全部

相关问题