4

如何将文件中的输入作为标准输入传输到在 shell 中运行的 erlang 程序以及独立运行?

我有一个文件hr.erl,我从 shell 编译它。它里面有一个函数,它接受来自标准输入的输入,使用io:fread(). 我写了一个带有守卫的案例表达式,如果它匹配{ok, [0]}它应该终止。而不是0,我实际上需要它eof

  1. 在shell中运行时如何发送eof?
  2. 我在每一行都有一个inp.txt包含值1 2 3的文件。0如何使用<管道运算符传递它?有什么类似的erl -hr <inp.txt吗?我可以将它通过管道传输到外壳中的标准输入吗?

到目前为止,这是我的程序(更新为包含eof)。

-module(hr).
-export([main/0]).    

r(L) ->
    case io:fread("", "~d") of
        eof -> 
            io:format("eof~n", []),
            ok;
        {ok, [0]} ->
            io:format("terminate~n", []),
            lists:reverse(L);
        {ok, [N]} ->
            io:format("inp ~p~n", [N]),
            r([N|L])
    end.

main() -> r([]).

从壳

1> c(hr).
{ok,hr}
2> hr:main().
1
inp 1
2
inp 2
3
inp 3
0
terminate
[1,2,3]

谢谢。

4

3 回答 3

3

这是 Erlang 常见问题解答之一:

http://www.erlang.org/faq/how_do_i.html#id49435

于 2013-10-28T19:47:13.163 回答
2

在这里寻找我所知道的 Erlang 中最快的面向行的 IO。注意命令行参数-noshell的用法。-noinput关键部分是

read() ->
   Port = open_port({fd, 0, 1}, [in, binary, {line, 256}]),
   read(Port, 0, [], []).

read(Port, Size, Seg, R) ->
  receive
    {Port, {data, {eol, <<$>:8, _/binary>> = Line}}} ->
      read(Port, Size + size(Line) + 1, [],
        [iolist_to_binary(lists:reverse(Seg, [])) | R]);
    {Port, {data, {eol, Line}}} ->
      read(Port, Size + size(Line) + 1, [Line | Seg], R);
    {'EXIT', Port, normal} ->
      {Size, [list_to_binary(lists:reverse(Seg, [])) | R]};
    Other ->
      io:format(">>>>>>> Wrong! ~p~n", [Other]),
      exit(bad_data)
  end.

编辑:请注意,面向行的 IO 在 R16B http://erlang.org/pipermail/erlang-questions/2013-February/072531.html中已修复,因此您不再需要此技巧。

EDIT2:有一个使用 fixed的答案file:read_line/1

于 2013-10-29T07:16:57.297 回答
1

使用escript时,我可以通过管道输入。编写没有模块或导出信息的erlang程序,具有main(_)功能,即以escript兼容的方式。cat然后我们可以使用类似管道输入

cat inp.txt | escript hr.erl

这有效,程序在遇到eof. 但是我仍然不知道为什么在使用 redirect operator 时它不起作用<

于 2013-10-29T15:33:24.537 回答