Bash

在腳本(.bashrc 等)中查找重複的別名和函式

  • October 18, 2021

這個網站說函式比別名更快,但他正確地指出別名更容易理解——當你想要一些非常簡單的東西並且不需要考慮傳遞參數時,別名是方便和明智的。在這種情況下,我的個人資料大約有 1,000 行,既可以作為我經常使用的功能和工具的來源,可以作為保留技術的手段,我可​​以參考和重用於其他任務,包括別名和裡面的功能。

但是一個問題是別名優先於函式,並且別名和函式的重新定義可能會導致問題(例如,如果我呼叫了一個函式gg,然後在腳本中稍後,偶然地,我呼叫了一個別名gg- 但如果稍後重新定義函式,再次作為函式,它會覆蓋先前的定義)。配置文件載入,但我最終遇到了問題。一種解決方案可能是消除所有別名並僅使用函式(有人這樣做嗎,我很想知道,因為如果我想這樣做alias m=man比更直覺和明智function m() { man $@; }?),但我仍然有函式重新定義的問題在這種情況下。

有沒有辦法解析腳本以回答:“對於別名或函式的每個聲明,向我顯示包含該項目的重新聲明(別名或函式)的所有行”?

嘗試這樣的事情:

$ 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::Dumpprintdd行用於調試。取消註釋以更好地了解此腳本的作用及其工作原理。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

引用自:https://unix.stackexchange.com/questions/673454