我试图从脚本的命令行中获取最后一个执行的命令,以备日后参考:
示例:
# echo "Hello World!!!"
> Hello World!!!
# my_script.sh
> echo "Hello World!!!"
并且脚本的内容为:
#!/usr/bin/ksh
fc -nl -1 | sed -n 1p
现在你注意到使用ksh
和fc
是一个内置命令,如果正确理解应该由任何POSIX兼容的shell实现。 [我知道这个功能是互动的,再次调用同一个fc
会产生不同的结果,但这不是关于讨论的问题]
上述作品到目前为止只有在从my_script.sh
调用ksh
时调用bash
,或者从#!/bin/bash
调用并将第1行脚本更改为{{ 1}}然后它也可以工作,如果外壳不同,它也不会。
我想知道是否有任何好方法可以实现上述目标而不受shell调用脚本的限制。我知道fc
是一个内置命令,它适用于每个shell,因此我的方法很可能完全不是我希望实现的。有更好的建议吗?
答案 0 :(得分:4)
我实际上尝试了这一点,但不能在不同的shell之间进行一致。
虽然
fc
-l`,
是用于显示$ SHELL历史的POSIX标准命令,实现细节可能不同。
至少 bash 和 ksh93 都将使用
报告最后一个命令fc -n -l -1 -1
但是,POSIX不保证shell历史记录会被转移到shell的新实例,因为这需要$HISTFILE
的存在。如果没有
目前,shell可能默认为$HOME/.sh_history
。
但是,此历史记录文件或命令历史记录列表在不同的shell之间不可移植。
POSIX Shell的描述 Command History List说:
当以交互方式使用sh实用程序时,它应保留一个命令列表 先前从HISTFILE环境命名的文件中的终端输入 变量。 此文件的类型,大小和内部格式未指定。
强调我的
这意味着您的脚本需要知道哪个shell写了该历史记录。
我尝试使用$SHELL -c 'fc -nl -1 -1'
,但是当$ SHELL引用bash时,这似乎不起作用。从bash调用ksh -c
...实际上有效。
我能让这个工作的唯一方法是创建一个函数。
last_command() { (fc -n -l -1 -1); }
在ksh 和 bash中,这将给出预期的结果。可以使用此函数的变体将结果写入其他位置。但是,无论什么时候打电话都会打破 来自与当前不同的过程。
您可以做的最好的事情就是创建这些功能并将它们输入您的 交互式shell。
答案 1 :(得分:0)
fc旨在以交互方式使用。我在cygwin / bash上测试了你的例子,结果不同了。即使在任何地方使用bash,fc命令在我的情况下都不起作用。
我认为fc会显示当前shell的最后一个命令(这里我不是说shell解释器,而是shell作为“处理盒”。所以问题更多的是它为什么适合你。
我认为没有一种干净的方法来实现你想要的东西,因为(也许我想念一些东西)你想要两个不同的过程(bash和你的魔法命令[my_script.sh]),默认情况下OS确保它们之间的隔离
你可以依靠你观察到的东西(不可移植,取决于shell解释器等)。
您不能依赖BASH历史记录,因为它在内存中(文件仅在退出时更新)。
您可以使用别名或功能(编辑:@Charles Duffy是对的)。在这种情况下,您将无法使用来自其他终端的“魔术命令”,但对于交互式使用,它可以完成这项工作。
编辑: 或者您可以提供两个命令:一个用于保存,另一个用于查找。在这种情况下,你管理自己的历史,但你必须明确保存每个令人痛苦的命令......
所以我寻找一个钩子。我找到了另一个帖子:https://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command
# At the beginning of the Shell (.bashrc for example)
save(){ history 1 >>"$HOME"/myHistory ; }
trap 'save' DEBUG
# An example of use
rm -f "$HOME"/myHistory
echo "1 2 3"
cat "$HOME"/myHistory
14 echo "1 2 3"
15 cat "$HOME"/myHistory
但是我发现它减慢了解释者的速度......
答案 2 :(得分:0)
有点费解,但我能够使用此命令在Linux上的zsh,bash,ksh和tcsh中获取最新命令:
history | tail -2 | head -1 | sed -r 's/^[ \t]*[0-9]*[ \t]+([^ \t].*$)/\1/'
警告:这使用GNU sed,因此如果你使用BSD,OS X等,你需要安装它;而且,tcsh将在命令本身之前显示命令的时间。我尝试时,常规csh
似乎没有正常运行的history
命令。