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 / 问题 / 671949
Accepted
YorSubs
YorSubs
Asked: 2021-10-06 06:15:20 +0800 CST2021-10-06 06:15:20 +0800 CST 2021-10-06 06:15:20 +0800 CST

Bash,查找内容与搜索字符串匹配的函数

  • 772

我想在 bash 中搜索所有定义的函数以获取一些搜索字符串。下面是一个开始,但我想在下一行消除所有没有$1跟空格的术语(即消除在该函数的主体中没有找到的所有条目)。

fu() { declare -f | grep -e \(\) -e $1; }

例如这个输出:

...
tt ()
untargz ()
urlfix ()
ver ()
    [ -f /etc/lsb-release ] && RELEASE="$(cat /etc/lsb-release | grep DESCRIPTION | sed 's/^.*=//g' | sed 's/\"//g') ";
vi. ()
vi.su ()
...

会减少到

...
ver ()
    [ -f /etc/lsb-release ] && RELEASE="$(cat /etc/lsb-release | grep DESCRIPTION | sed 's/^.*=//g' | sed 's/\"//g') ";
...

如果可以确定并完整显示每个匹配函数,则更好的方法(如果可能)将是。

我的设想大致为:

  • 收集函数的名称及其正文中的搜索字符串(函数的名称始终是匹配前一行上的一个单词,从 at 开始,^后跟一个空格,然后以 结尾的行()$),然后command -V在其中的每一个上使用名称,或者,再做declare -f一次,但这次,使用这些名称并将它们之后的所有内容从{to匹配}(在哪里{和}在单行上)^- 我知道 grep/awk/sed 可以对那些有这些知识的人做惊人的事情.

最终结果将运行fu awk,它将向我显示函数awk体中包含的每个函数的定义。

bash text-processing
  • 2 2 个回答
  • 323 Views

2 个回答

  • Voted
  1. Best Answer
    AdminBee
    2021-10-06T06:38:45+08:002021-10-06T06:38:45+08:00

    awk想到管道接收端的以下命令:

    declare -f | awk -v srch="pattern" 'NF==2 && $2=="()"{if (m) print buf; buf=""; m=0}
                                        buf && index($0,srch){m=1}
                                        {buf=buf ORS $0}
                                        END{if (m) print buf}'
    

    buf这个想法是在解析 的输出时将每个函数的声明和主体存储在缓冲区中declare -f,但仅在找到搜索字符串时才打印缓冲区。

    • 如果程序遇到仅包含两个字段(= 空格分隔的“单词”)的行,其中第二个字段是(). 如果在解析前一个函数时找到匹配项(由标志为 1 表示),将打印m缓冲区。buf缓冲区和标志都将被重置。
    • 搜索词作为awk变量传递给程序srch。如果在当前行找到(index函数返回非零结果),则m标志设置为 1,但前提是我们不在函数声明开始的行(表示buf不为空),否则匹配在函数名称中也将计算在内。
    • 每行都将附加到缓冲区buf,并通过输出记录分隔符ORS(默认为换行符)与先前的内容分隔。
    • 最后,如果找到匹配项,则执行另一次检查,如果找到,则打印缓冲区。如果没有该检查,将永远不会考虑最后一个函数定义。

    笔记

    index()该程序使用 的函数执行全字符串搜索awk。如果您希望搜索基于正则表达式匹配,则需要将条件从

    index($0,srch)
    

    至

    $0~srch
    

    (但与往常一样,请注意搜索包含对正则表达式具有特殊含义的字符的字符串变得更加麻烦)。

    • 5
  2. Stéphane Chazelas
    2021-10-06T07:30:26+08:002021-10-06T07:30:26+08:00

    对于那些想要zsh在

    typeset -f '<dummy>' ${(k)functions[(R)pattern]}
    

    <dummy>覆盖没有匹配功能的情况。或者更清洁的方式:

    () { (($#)) && typeset -f -- "$@"; } ${(k)functions[(R)pattern]}
    

    在bash中,您可以执行类似的操作:

    compgen -A function | (
      ret=1
      while IFS= read -r fn; do
        def=$(typeset -f -- "$fn") &&
          [[ ${def#*'()'} = pattern ]] &&
          printf '%s\n' "$def" &&
          ret=0
      done
      exit "$ret"
    )
    

    尽管这是非常低效的,因为函数名称列表一次读取一个字节(因为read' 的输入是管道),并且每个函数都派生一个进程。它可以通过以下方式进行优化:

    compgen -A function | (
      readarray -t functions
      for fn in "${functions[@]}"; do
        typeset -f -- "$fn" && printf '\0'
      done
    ) | (
      ret=1
      readarray -td '' fn_definitions
      for def in "${fn_definitions[@]}"; do
        [[ ${def#*'()'} = pattern ]] &&
          printf '%s\n' "$def" &&
          ret=0
      done
      exit "$ret"
    )
    

    readarray,相反read,不需要一次读取一个字节的输入,因为它无论如何都会消耗所有输入。我们用 NUL 字符分隔函数定义,因为无论如何bash(与 相反zsh)不能将该字符存储在其函数定义/名称或变量内容中,然后我们可以使用readarray -td ''(这需要 bash-4.4+)将其分解为一个数组。

    这避免了必须依赖诸如存在的启发式算法()(这也很可能出现在函数的主体中)来猜测每个函数定义在typeset -f.

    • 4

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

  • 如何更改字符大小写(从小到大,反之亦然)?同时[重复]

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