【问题标题】:How to output result to shell?如何将结果输出到shell?
【发布时间】:2015-02-21 20:34:18
【问题描述】:

我有一个shell脚本,script.sh:

#!/bin/bash
FIRST_ARGUMENT="$1"

swipl -s script4.pl $FIRST_ARGUMENT

prolog.pl:

:- initialization main.

query :-
        current_prolog_flag(argv, Argv),
        concat_atom(Argv, ' ', Atom),
        read_term_from_atom(Atom, Term, []),
        call(Term).

main :-
        catch(query, E, (print_message(error, E), fail)),
        halt.
main :-
        halt(1).

b(a).
a(c, d) :- writeln('I was called!').

现在如果我从命令行调用脚本:

sh s.sh 'a(c,d).'

将输出"I was called!"

但如果我运行一个查询,除了是/否答案:

sh s.sh 'b(a).'

它告诉我的只是:script4.pl compiled 0.00 sec, 7 clauses。当我想要的是“真实”时,因为找到了与输入匹配的事实。我怎样才能得到结果?

我想从 Rake(Ruby 衍生产品)查询我的 Prolog 程序。我想脚本是一种简单的方法来做到这一点,但也许它不够强大?

【问题讨论】:

  • 您需要确定是否真的需要将程序作为脚本调用,而不是使用顶层(解释器)。几乎没有理由使用脚本而不是顶层,除了可能是批处理文本处理 (?)。
  • @Boris 我更新了这个问题。也许我可以做些什么来让这变得更好。
  • 您可以使用 SWI-Prolog 命令行选项 --quiet-q 将有关编译文件所用时间和其中子句数量的信息性消息静音。

标签: macos prolog swi-prolog prologscript


【解决方案1】:

由于您希望 prolog 生成的输出通常严格在​​其交互式 shell 中完成,因此这是需要某种类型的 crude 实现的事情之一。这个特殊的可能被认为是极端的,但它确实有效

#!/bin/bash
FIRST_ARGUMENT="$1"

swipl -l script4.pl $FIRST_ARGUMENT',halt(n).' 2>&1 | sed 's/ERROR: halt\/1.*/True/g'

结果:

$ sh s.sh 'b(a)'
True

当然,您可以提出自己的开箱即用方法,我鼓励这样做。

【讨论】:

  • 任何尝试这个的人都要小心密切关注这个答案。请注意,参数b(a) 没有'.'。因为现在这是 shell 命令的一部分。
【解决方案2】:

一种简单但粗略的方法是将writeln(true)writeln(false) 分别添加到main/0 的每个成功和失败子句中:

main :- catch(query, E, (print_message(error, E), fail)),
        writeln(true),
        halt.
main :- writeln(false),
        halt(1).

虽然我确信有更好的解决方案......

【讨论】:

  • 虽然 I'L'I 的方法很有趣,但我使用这种方法是因为它适用于 windows 和 mac。我两个都需要。
  • 这个方法看起来确实更通用,在有限的意义上它让 Prolog 代码决定生成什么样的输出。相反,I'L'I 的方法似乎在 unix 方面提供了一定的保证,确保 shell 脚本的某些输出。我认为,重要的是输出“真实”。和'假'。只对顶层的 Prolog 有一定的认识。当我们将 Prolog 程序用作链接到其他程序的可执行文件时,我们只希望它们输出我们需要的任何类型的数据。使用 Prolog 来验证事实是一个非常特殊的情况。
  • @aBathologist,说得好——我回答中的方法是我一时兴起想出的。正如 P.Brian.Mackey 所说,虽然它是 fun 的,但我认为应该首选使用本身具有 prolog 处理的解决方案。很高兴在每个人的回答中看到这种想法,因为它确实允许人们超越以前可能做过的事情。
  • @l'L'l 同意!看到各种方法不同的解决方案真的很有帮助和令人耳目一新。让我更好地了解这些工具的灵活性。
【解决方案3】:

通常,shell 脚本在成功时返回零,在失败时返回一个非零整数,解释为错误代码。因此,您可以使用标准的 halt/1 谓词返回零或例如一个取决于您的查询,分别是成功还是失败。您已经在这样做了,但您可以通过以下方式使其更加清晰:

main :-
    (   query ->
        halt(0)
    ;   halt(1)
    ).

如果查询可能引发异常,请使用标准的catch/3 谓词包装它:

main :-
    (   catch(query, _, fail) ->
        halt(0)
    ;   halt(1)
    ).

也可以使用异常来选择退出值:

main :-
    (   catch(query, Error, error_handler(Error)) ->
        halt(0)
    ;   halt(1)
    ).

error_handler(error1) :- halt(2).
error_handler(error2) :- halt(3).
...

在这种情况下,0 表示成功,1 表示失败,任何其他整数都表示相应的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    • 2015-05-07
    • 2011-01-08
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    相关资源
    最近更新 更多