在 IEx Ports 的标准错误中强制回车 returns?
Force carriage returns in IEx Ports' stderr?
如果我在 IEx 中为将任何内容打印到 stderr 的脚本打开一个端口,输出的 none 将使用回车符 returns 打印。我怎样才能解决这个问题?我是 运行 无法控制其输出的外部软件,所以我不能只手动添加 returns。
例子
在/tmp/run.sh
#!/usr/bin/env bash
>&2 echo -e "line 1\nline 2\nline 3\nline 4"
在 IEx 中 shell
iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
line 1
line 2
line 3
line 4
您可以 运行 在换行符前插入回车 return 的包装器下的脚本。这是一个使用 bash
和 perl
的包装器:
#!/usr/bin/env bash
"$@" 2>&1 | perl -pe 's/\n/\r\n/' 1>&2
这是另一个使用 bash
和 unix2dos
的方法:
#!/usr/bin/env bash
"$@" 2>&1 | unix2dos 1>&2
基本上,任何可以读取原始程序的stderr
,用回车符return和换行符组合替换换行符,然后将结果写入stderr
的东西都可以。
将这些解决方案之一放入名为 /tmp/lf.sh
的文件中。下面我们 运行 它来自 iex 与您的原始 /tmp/run.sh
,首先是原始脚本,然后是包装器:
iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
#Port<0.5>
iex(2)> line 1
line 2
line 3
line 4
nil
iex(3)> Port.open({:spawn_executable, "/tmp/lf.sh"}, [args: ["/tmp/run.sh"]])
#Port<0.6>
iex(4)> line 1
line 2
line 3
line 4
nil
iex(5)>
我有另一个快速但肮脏的解决方案(仅限 Elixir)
Port.open({:spawn_executable, "/tmp/run.sh"}, [:use_stdio, :stderr_to_stdout, :binary, :hide]); receive do
{_port, {:data, line}} -> String.split(line,"\n", trim: true) |> Enum.each(fn(x)-> IO.puts(x) end)
end
问题是你想用这些数据做什么。
有关 link 的更多信息 https://bugs.erlang.org/browse/ERL-802
引用:
elixir --no-halt -e ':user_drv.start();Port.open({:spawn, "bash -c '\''>&2 echo \"stderr\nline2\"'\''"}, [:binary])' 2> err.log
如果我在 IEx 中为将任何内容打印到 stderr 的脚本打开一个端口,输出的 none 将使用回车符 returns 打印。我怎样才能解决这个问题?我是 运行 无法控制其输出的外部软件,所以我不能只手动添加 returns。
例子
在/tmp/run.sh
#!/usr/bin/env bash
>&2 echo -e "line 1\nline 2\nline 3\nline 4"
在 IEx 中 shell
iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
line 1
line 2
line 3
line 4
您可以 运行 在换行符前插入回车 return 的包装器下的脚本。这是一个使用 bash
和 perl
的包装器:
#!/usr/bin/env bash
"$@" 2>&1 | perl -pe 's/\n/\r\n/' 1>&2
这是另一个使用 bash
和 unix2dos
的方法:
#!/usr/bin/env bash
"$@" 2>&1 | unix2dos 1>&2
基本上,任何可以读取原始程序的stderr
,用回车符return和换行符组合替换换行符,然后将结果写入stderr
的东西都可以。
将这些解决方案之一放入名为 /tmp/lf.sh
的文件中。下面我们 运行 它来自 iex 与您的原始 /tmp/run.sh
,首先是原始脚本,然后是包装器:
iex(1)> Port.open({:spawn_executable, "/tmp/run.sh"}, [])
#Port<0.5>
iex(2)> line 1
line 2
line 3
line 4
nil
iex(3)> Port.open({:spawn_executable, "/tmp/lf.sh"}, [args: ["/tmp/run.sh"]])
#Port<0.6>
iex(4)> line 1
line 2
line 3
line 4
nil
iex(5)>
我有另一个快速但肮脏的解决方案(仅限 Elixir)
Port.open({:spawn_executable, "/tmp/run.sh"}, [:use_stdio, :stderr_to_stdout, :binary, :hide]); receive do
{_port, {:data, line}} -> String.split(line,"\n", trim: true) |> Enum.each(fn(x)-> IO.puts(x) end)
end
问题是你想用这些数据做什么。
有关 link 的更多信息 https://bugs.erlang.org/browse/ERL-802 引用:
elixir --no-halt -e ':user_drv.start();Port.open({:spawn, "bash -c '\''>&2 echo \"stderr\nline2\"'\''"}, [:binary])' 2> err.log