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 / 问题 / 673454
Accepted
YorSubs
YorSubs
Asked: 2021-10-17 00:56:27 +0800 CST2021-10-17 00:56:27 +0800 CST 2021-10-17 00:56:27 +0800 CST

在脚本(.bashrc 等)中查找重复的别名和函数

  • 772

这个网站说函数比别名更快,但他正确地指出别名更容易理解——当你想要一些非常简单的东西并且不需要考虑传递参数时,别名是方便和明智的。在这种情况下,我的个人资料大约有 1,000 行,既可以作为我经常使用的功能和工具的来源,也可以作为保留技术的手段,我可​​以参考和重用于其他任务,包括别名和里面的功能。

但是一个问题是别名优先于函数,并且别名和函数的重新定义可能会导致问题(例如,如果我调用了一个函数gg,然后在脚本中稍后,偶然地,我调用了一个别名gg- 但如果稍后重新定义函数,再次作为函数,它会覆盖先前的定义)。配置文件加载,但我最终遇到了问题。一种解决方案可能是消除所有别名并仅使用函数(有人这样做吗,我很想知道,因为如果我想这样做alias m=man比更直观和明智function m() { man $@; }?),但我仍然有函数重新定义的问题在这种情况下。

有没有办法解析脚本以回答:“对于别名或函数的每个声明,向我显示包含该项目的重新声明(别名或函数)的所有行”?

bash alias
  • 2 2 个回答
  • 170 Views

2 个回答

  • Voted
  1. Best Answer
    cas
    2021-10-17T05:13:20+08:002021-10-17T05:13:20+08:00

    尝试这样的事情:

    $ cat find-dupes.pl
    #!/usr/bin/perl
                                                             
    use strict;                                                                                                        
    #use Data::Dump qw(dd);                         
    
    # Explanation of the regexes ($f_re and $a_re):
    #                                                         
    # Both $f_re and $a_re start with '(?:^|&&|\|\||;|&)' to anchor
    # the remainder of the expression to the start of the line or
    # immediately after a ;, &, &&, or ||. Because it begins with
    # '?:', this is a non-capturing sub-expression, i.e. it just    
    # matches its pattern but doesn't return what it matches. 
                                                             
    # $f_re has two main sub-expressions. One to match 'function name ()'
    # (with 'function ' being optional) and the other to match
    # 'function name () {' (with the '()' being optional).
    #
    # Each sub-expression contains more sub-expressions, with one of
    # them being a capture group '([-\w.]+)' and the rest being       
    # non-capturing (they start with '?:'). i.e. it returns the
    # function name as either $1 or $2, depending on which subexp                                               
    # matched.
    my $f_re = qr/(?:^|&&|\|\||;|&)\s*(?:(?:function\s+)?([-\w.]+)\s*\(\)|function\s+([-\w.]+)\s+(?:\(\))?\s*\{)/;
    
    # $a_re matches alias definitions and returns the name of
    # the alias as $1.
    my $a_re = qr/(?:^|&&|\|\||;|&)(?:\s*alias\s+)([-\w.]+)=/;
    
    # %fa is a Hash-of-Hashes (HoH) to hold function/alias names and
    # the files/lines they were found on. i.e an associative array
    # where each element is another associative array.  Search for
    # HoH in the perldsc man page.
    my %fa;
    
    # main loop, read and process the input
    while(<>) {
      s/#.*|^\s*:.*//;  # delete comments
      s/'[^']+'/''/g;   # delete everything inside ' single-quotes
      s/"[^"]+"/""/g;   # delete everything inside " double-quotes
      next if /^\s*$/;  # skip blank lines
    
      while(/$f_re/g) {
          my $match = $1 // $2;
          #print "found: '$match':'$&':$ARGV:$.\n";
          $fa{$match}{"function $ARGV:$."}++;
      };
    
      while(/$a_re/g) {
          #print "found: '$1':'$&':$ARGV:$.\n";
          $fa{$1}{"alias $ARGV:$."}++;
      };
    
      close(ARGV) if eof;
    };
    
    #dd \%fa;
    
    # Iterate over the function/alias names found and print the
    # details of duplicates if any were found.
    foreach my $key (sort keys %fa) {
      my $p = 0;
    
      # Is this function/alias ($key) defined more than once on
      # different lines or in different files?
      if (keys %{ $fa{$key} } > 1) {
        $p = 1;
      } else {
        # Iterate over the keys of the second-level hash to find out
        # if there is more than one definition of a function/alias
        # ($key) in the same file on the same line ($k)
        foreach my $k (keys %{ $fa{$key} }) {
          if ($fa{$key}{$k} > 1) {
            $p = 1;
    
            # break out of the foreach loop, there's no need to keep
            # searching once we've found a dupe
            last;
          };
        };
      };
    
      # print the details if there was more than one.
      print join("\n\t", "$key:", (keys %{$fa{$key}}) ), "\n\n" if $p;
    };
    

    注释掉的Data::Dump、print和dd行用于调试。取消注释以更好地了解此脚本的作用及其工作原理。dd该模块的函数输出Data::Dump特别有趣,因为它向您展示了%faHoH 的结构(和内容)。 Data::Dumpperl 中不包含它,它是您需要安装的库模块。您没有提到您使用的是什么发行版,但如果您使用的是 debian/ubuntu/mint/etc,您可以使用sudo apt install libdata-dump-perl. 其他发行版可能将其打包在稍微不同的名称下。否则,您可以使用cpan.

    示例输出(使用包含评论中的别名以及一些虚拟函数的文件):

    $ cat yorsub.aliases 
    function foo () { echo ; }
    bar () { echo ; }
    bar () { echo ; }
    function baz () { echo ; } && quux () { echo ; } ; alias xyz=abc; 
    type tmux  &> /dev/null && alias t='tmux'
    alias cd-='cd -'; alias cd..='cd ..'; alias u1='cd ..'; alias u2='cd ../..'; alias u3='cd ../../..'; alias u4='cd ../../../../..'; alias u5='cd ../../../../../..'; alias u6='cd ../../../../../../..' alias back='cd -'; alias cd-='cd -'; alias .1="cd .."; alias .2="cd ../.."; alias .3="cd ../../.."; alias .4="cd ../../../.."; alias .5="cd ../../../../.."; alias .6='cd ../../../../../../..'
    function cd.. { cd .. ; }
    function abc () { xyx "$@" }; abc () { xyz } ; function abc { xyz }; alias abc=xyz
    
    $ ./find-dupes.pl yorsub.aliases    
    abc:
            function yorsub.aliases:8
            alias yorsub.aliases:8
    
    bar:
            function yorsub.aliases:3
            function yorsub.aliases:2
    
    cd-:
            alias yorsub.aliases:6
    
    cd..:
            alias yorsub.aliases:6
            function yorsub.aliases:7
    
    
    • 1
  2. ilkkachu
    2021-10-18T00:42:40+08:002021-10-18T00:42:40+08:00

    简单的 grep 查找定义,但不检查重新定义:

    $ grep -onE 'alias [[:alnum:]_]+=|[[:alnum:]_]+\(\)' .bashrc .aliases
    .bashrc:47:alias foo=
    .bashrc:47:alias bar=
    .bashrc:49:asfdasdf()
    .aliases:3:alias ls=
    .aliases:6:alias foo=
    

    这个 Perl 单行程序保持计数,因此它可以标记重新定义:

    $ perl -lne 'while( /alias (\w+)=|(\w+)\(\)/g ) { 
                     $name = $1 // $2; $count{$name} += 1; 
                     printf "\"%s\" %s in %s line %s%s\n", $name, $count{$name} > 1 ? "REDEFINED" : "defined", $ARGV, $. 
                 }' .bashrc .aliases 
    "foo" defined in .bashrc line 47
    "bar" defined in .bashrc line 47
    "asfdasdf" defined in .bashrc line 49
    "ls" defined in .aliases line 53
    "foo" REDEFINED in .aliases line 56
    

    (输入文件的顺序会影响哪个文件未被标记为“重新定义”。)

    • 1

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

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

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

  • `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