AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 774159
Accepted
dhm
dhm
Asked: 2024-04-09 15:05:23 +0800 CST2024-04-09 15:05:23 +0800 CST 2024-04-09 15:05:23 +0800 CST

如何按照历史记录将我自己的代码片段放在命令行上?

  • 772

我有数百个经过测试和尝试的命令和片段保存在各种文本文件中。当我需要重复使用时,我会找到并复制/粘贴到命令行。尽管可靠,但这是一种笨拙的方法。与此相比,我们可以从历史文件中直接检索旧命令到命令行并准备编辑和使用。我如何模拟此功能并使用我自己的命令集?

我有脚本来搜索(使用 fzf)、查找并将我自己的命令附加到历史文件中。这效果很好。但它确实使历史文件变得混乱。

这是我的脚本:

find ~ -type f | fzf --preview-window=up:50% --header "ENTER:less; ^s:snip to history" --bind "enter:execute(less {})"  --bind "ctrl-s:execute(cat {} | fzf -m --preview-window=:hidden  >>~/.bash_history)"; history -n
command-line
  • 3 3 个回答
  • 253 Views

3 个回答

  • Voted
  1. Kamil Maciorowski
    2024-04-09T19:12:57+08:002024-04-09T19:12:57+08:00

    一个用于交互式 Bash 的快速而肮脏的装置(我的bash --version打印5.2.15):

    1. 将您想要的(单行)命令放入~/.commands.

    2. 定义以下辅助函数:

      _get_command () {
         READLINE_LINE="$(<~/.commands fzf -1 --query="$READLINE_LINE")" &&
         READLINE_POINT="${#READLINE_LINE}"
      }
      
    3. 绑定到按键(按键序列):

      bind -x '"\C-x\C-r":_get_command'
      
    4. 开始使用Ctrl+ x, Ctrl+ r。

    笔记:

    • READLINE_POINT="${#READLINE_LINE}"应该将光标放在最后。Bash 5 想要字符长度,上面的代码可以工作;但 Bash 4 需要字节。要在 Bash 4 中处理非 ASCII 文本,请使用

      READLINE_POINT="$(printf '%s' "$READLINE_LINE" | wc -c)"
      

      (我从这个答案中了解到)。

    • 因为~/.commands您可以发明自己的格式来指定或编码每个命令所需的光标位置。改进帮助程序功能以根据您的格式READLINE_LINE进行设置。READLINE_POINT

      另一方面,~/.commands仅存储文字命令很简单并且可以很好地与--query="$READLINE_LINE".

    • 对于多行命令,您需要fzf --read0和 中的空终止条目~/.commands。维护这种格式比编辑换行符终止的条目更困难。


    写完上面的内容后,我决定想要这个功能。这是我更复杂的解决方案(放入~/.bashrc):

    export SNIPPETFILE
    
    _del_snippet () {
       SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
       printf '%s\0' "$1" | sort -zm -- "$SNIPPETFILE" - | uniq -zu >"$SNIPPETFILE"~ \
       && mv -- "$SNIPPETFILE"~ "$SNIPPETFILE"
       cat -- "$SNIPPETFILE"
    }
    export -f _del_snippet
    
    _get_snippet () {
       SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
       local line
       line="$(<"$SNIPPETFILE" fzf -1 --read0 --query="$READLINE_LINE" \
          --border top --border-label 'Enter to confirm, Ctrl+y to delete entry, Ctrl+c to abort' \
          --bind 'ctrl-y:reload-sync(exec bash -c "_del_snippet \"\$1\"" bash {})')" \
       && READLINE_LINE="$line" \
       && READLINE_POINT="${#READLINE_LINE}"
    }
    bind -x '"\C-x\C-r":_get_snippet'
    
    _put_snippet () {
       [[ "$READLINE_LINE" =~ ^[[:space:]]*$ ]] && return 0
       SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
       if
          touch -- "$SNIPPETFILE" \
          && printf '%s\0' "$READLINE_LINE" | sort -zum -- "$SNIPPETFILE" - >"$SNIPPETFILE"~ \
          && mv -- "$SNIPPETFILE"~ "$SNIPPETFILE"
       then
          printf 'command stored in `%s'\''\n' "$SNIPPETFILE" >&2
       else
          printf 'storing in `%s'\'' failed\n' "$SNIPPETFILE" >&2
          return 1
       fi
    }
    bind -x '"\C-x\C-m":_put_snippet'
    

    用法:

    • Ctrl使用+ x, Ctrl+存储当前命令行m。

    • 使用Ctrl+ x、Ctrl+r从存储的命令列表中进行选择。如果有一个与您已经输入的内容完全匹配,它将被带到命令行。如果还有更多,您将可以交互选择。

    • 交互选择时,Ctrl+y会删除突出显示的条目。

    笔记:

    • 支持多行命令,但为了正确存储它们,您不能点击Enter(引号内或之后\),否则会出现辅助提示。您需要从历史记录中引入多行命令,或者通过按Ctrl+ v、Ctrl+使命令成为多行j,这样就不会出现辅助提示,您仍然可以编辑整个命令。然后Ctrl+ x, Ctrl+m就能存储整个多行命令。

      当您以交互方式选择这些行时,它们看起来不像多行命令,但它们将作为多行带到命令行。

      这会产生一个很好的副作用:您可以存储带标签的命令。这个

      # description (label) here
      :
      actual_command args
      

      在列表中将如下所示:

      # description (label) here : actual_command args
      

      但在被选择之后它就会起作用。

    • 默认文件是$HOME/.snippets. 您可以通过设置并export使用名为 的变量来使用另一个路径名SNIPPETFILE。带有后置波浪号的路径名(例如$HOME/.snippets~)也将用于维护。

    • 在 Bash 5.2.15 中使用 GNUsort和 GNU进行测试uniq(使用非可移植选项)。

    • 可能仍然存在错误。

    • 4
  2. Best Answer
    user9101329
    2024-04-10T17:51:07+08:002024-04-10T17:51:07+08:00

    可能值得探索 xdotool 来解决您的问题。

    根据手册页:

    xdotool 允许您以编程方式(或手动)模拟键盘输入和鼠标活动、移动窗口和调整窗口大小等。

    因此,您可以定义一个别名来帮助您找到您最喜欢的命令并告诉 xdotool 将其放置在命令行上。例如:

    $ alias my_command='stty -echo &&  xdotool type "$(cat any_list | fzf)" ; stty echo'
    

    这将允许您从文件“any_list”中提取任何文本行并将其放置在命令行上。如果该文本恰好是您的旧命令之一,那么您就可以编辑并执行它了。

    您当前的设置中可能已经有 xdotool。如果没有,下载并安装它非常容易 - 例如https://installati.one/install-xdotool-debian-12

    • 2
  3. aviro
    2024-04-10T17:24:15+08:002024-04-10T17:24:15+08:00

    中bash,shell-expand-line(键盘快捷键M-C-e,通常是ALT+ CTRL+ e)将“像 shell 一样扩展行。这将执行别名和历史扩展以及所有 shell 单词扩展”。

    因此,实现您想要的最简单的方法是将要插入命令行的命令分配给某个变量,写入变量的名称,然后按此键序列以展开其内容。

    例如:

    $ COMMAND="echo hello world"
    

    现在在命令行中写入变量的名称($COMMAND在本例中),然后按ALT+ CTRL+ e。$COMMAND将自动在当前行中替换为其内容。

    $ echo hello world
    

    $(!!)或者,您可以通过编写然后单击序列,将命令行替换为上一个命令的输出。例如:

    $ grep ps .snippets
    ps -fp $$
    $ $(!!)
    

    在该点单击ALT+ CTRL+e会将命令行替换为命令的输出grep。

    $ ps -fp $$
    
    • 1

相关问题

  • ip 命令是否支持通配符?

  • 需要许多参数的实用程序的推荐界面是什么?[关闭]

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • 使 mysql CLI 以交互方式向我询问密码

  • 没有服务器的命令行 pub/sub?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve