2

我希望能够编写一个程序,当你输入命令时,它会做一些事情,比如计算你使用的次数cd。与此类似的东西:

[ : ~ $] cd public_html
Congratulations! You've earned the Badge 'cd master!'. Level up!

到目前为止,我所有的 C++ 文件包括:

#include <iostream>

int main(int argc, char* argv[]) {
    int counter = 0;
    for (int i = 1; i < argc; i++) {
        std::cout << argv[i] << std::endl;
        if (argv[i] == "cd")
            std::cout << "Badge earned 'cd master!' +5120 experience points" << std::endl;
    }
    return 0;
}

因为它反映了一种尝试的解决方案,涉及:

#!/bin/sh
bash | tee ./main

bind 'RETURN: "echo $(!!) | tee ~/.main \n"'

我决定一起去

export PROMPT_COMMAND='history | tail -n1'

但这意味着必须解析输出。

完成此任务的最简单方法是什么?

编辑

这是我设法制作的:

#!/bin/sh
export COUNTER=0
export MAXWIDTH=10
export TNL=1000
update_prompt() {
  export PS1="> "
}
cd() {
  COUNTER=$(($COUNTER + 25));
  echo +25;
  builtin cd $@;
}
help() {
  echo "custom commands are: score";
}
score() {
  echo $COUNTER"/"$TNL
  BAR=$(yes "#" | head -n 10 | tr -d '\n')
  OVERLAY=$(yes "%" | head -n 10 | tr -d '\n')
  WIDTH=$(echo "$COUNTER*$MAXWIDTH/$TNL" | bc)
  FIRST=${BAR:0:WIDTH}
  SECOND=${OVERLAY:0:$((MAXWIDTH-WIDTH))}
  echo "["$FIRST$SECOND"]"
}
exit() {
    echo "Bye bye";
    builtin exit $@;
}
export -f update_prompt
export -f cd # export the function
export -f help
export -f score
export -f exit

bash # run subshell with the exported functions
update_prompt
4

3 回答 3

2

cd一个简单的解决方案是在 shell 本身内覆盖 shell 的命令。例如,在 Bash 或 ZSH 中:

cd() {
  echo "Congratulations";
  builtin cd $@;
}

(例如,这用于autoenv等项目。)

您可以对所有其他命令执行相同的操作。您也可以从那里调用您的 C++ 代码。

如果您想将其放入脚本中,例如将其命名为learn-bash.sh

cd() { ... }
export -f cd # export the function

bash # run subshell with the exported functions

另一种解决方案,你有更多的权力,但涉及更多:获取 Bash 的源代码(它是 C)并扩展它(通过 C 或 C++)。然后你基本上可以为所欲为。你有一切直接在那里,即解析的命令等。

于 2013-10-16T12:28:53.383 回答
0

I've done something similar a while ago, and here's the solution I've found.

You want to add the following lines to .bashrc:

hook() {
    whatever "$@"
}

invoke_hook() {
    [ -n "$COMP_LINE" ] && return
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return
    local command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    hook "$command"
}

trap 'invoke_hook' DEBUG

Replace whatever with your C++ program. This will execute your hook before each command, and will pass the original command as the arguments.

于 2013-10-16T12:40:28.483 回答
0

COMMAND_PROMPT在 bash 中执行每个命令之后。您可以使用它history来查看最后使用的命令。

您可以在此处阅读PS1、PS2、PS3 和 COMMAND_PROMPT 如何在 bash 中工作。

在SO上已经有一些关于这个问题的答案:

如何拦截包含特定字符串的命令?

bash:如何拦截每个命令

bash:如何拦截命令行并根据内容执行各种操作?

于 2013-10-16T12:27:42.273 回答