如何共享我的.bashrc
文件但仅共享相关部分?
例如,我在以下位置创建了 5 个函数.bashrc
:
f1() {
...
}
f2() {
f1
...
}
f3() {
f2
...
}
f4() {
f1
f3
...
}
f5() {
...
}
案例一:我想分享f5()
给同事,所以我只需复制f5()
粘贴给他们
情况2:我想分享f3()
,所以我想复制f3()
并递归f2()
和f1()
。
情况3:我想分享f4()
,所以我想复制f3()
并递归地f2()
与f1()
;但我只想复制f1()
一次,即使在和f1()
中都被调用。f3()
f2()
现在我手动查找并复制,但很容易出错;可以自动完成吗?我不使用Python。假设所有函数都在同一个.bashrc
文件中,都是我定义的bash函数。
答案1
看一下展平.sh。我写这个是为了我可以将所有别名和函数源到一个 shell 脚本中,并将其扁平化为所需的内容,所以就像您现在所处的情况一样。
因此,像example.lib
这样(或你的.bashrc
):
f1() {
echo "I am f1"
}
f2() {
f1
}
f3() {
f2
}
f4() {
f1
f3
}
f5() {
:
}
example.sh
和这样的脚本:
#!/usr/bin/env -S bash -
. /path/to/example.lib
f4
你跑flatten.sh example.sh
并得到
#!/usr/bin/env -S bash -
f1() {
echo "I am f1"
}
f2() {
f1
}
f3() {
f2
}
f4() {
f1
f3
}
f4
答案2
以下 perl 脚本是一个概念验证演示,用于从脚本中提取函数名称和定义。它构建一个%funcs
包含每个函数代码的哈希(关联数组)。然后,它搜索每个函数定义,找出该函数中调用了哪些其他函数,并将该信息存储在名为 的散列中的散列(“HoH”,一个散列,其中每个元素都是另一个散列。请参阅man perldsc
)中%contains
。
最后,它从命令行上提供的函数名称列表开始,构建要打印的函数列表(另一个称为 的哈希值%out
),然后打印它们。
该脚本在概念上相当简单且暴力 - 没有努力优化代码的性能或简洁性。
注意:这不是一个完整的 shell 代码解析器(远非如此,它充其量只是一个简单的正则表达式标记匹配器)。它仅针对定义上面示例函数的 shell 代码、我自己的 ~/.bashrc 以及来自set
内置函数输出的 stdin 进行了测试(它打印定义的函数以及变量,即使在help set
或在 bash 手册页中)。
其他 shell 代码有可能(事实上,很有可能)会破坏这一点。在这种情况下,您(至少)需要细化标记提取正则表达式,并且可能还需要细化查找函数定义开头的正则表达式。可能还有删除带引号的字符串和注释的代码。它们是最有可能失败的三个点。
#!/usr/bin/perl
use strict;
use v5.10;
# primitive arg handling to separate function names from
# input files on the command line.
#
# if an argument is a filename that exists, treat it as
# an input file. If not, treat it as a function name to
# search for.
my (@args,%find) = ();
foreach (@ARGV) {
if (-e $_) {
push @args, $_; # array of input files to process
} else {
$find{$_} = 1; # hash of function name(s) to search for.
}
};
@ARGV = @args;
# Main loop, read and process the input.
# Build up a hash called %funcs with key = function name
# and val = function code.
my %funcs = ();
while(<>) {
state ($fname, $in_func, $counter);
# state variables:
# $fname - name of current function
# $in_func - are we in a function definition
# $counter - how many { and } have we seen in this function?
if (/^(?:function)?\s*([^\$(=\s]*)\s*[(]/) {
$fname = $1;
$funcs{$fname} = $_;
$in_func = 1;
# cuddled braces begin on same line as function name. uncuddled don't.
my $cuddled = () = $_ =~ (/{/g); # count of { on this line
next unless $cuddled;
$cuddled -= () = $_ =~ (/}/g); # subtract count of }s on line
$counter = $cuddled;
$in_func = $cuddled;
next;
};
if ($in_func) {
$funcs{$fname} .= $_;
my $plus = () = $_ =~ (/{/g); # count of {s on line
my $minus = () = $_ =~ (/}/g); # count of }s on line
$counter += $plus - $minus;
$in_func = ($counter > 0);
}
};
###
### Now determine which functions to print, then print them.
###
my %contains = ();
my $match = join("|", keys %funcs);
foreach my $f (keys %funcs) {
# ignore everything in quoted strings and comments by
# copying the current function to variable $function and
# stripping unwanted junk. ignore unquoted array references too.
my $function;
($function = $funcs{$f}) =~ s/"[^"]*"|'[^']*'|#.*$|\$\{[^}]}//mg;
# find tokens that *look like* calling one of our known function names
my (@tokens) = ($function =~ /(?:^|;|&{1,2}|\|{1,2}|[({])\s*($match)\b(?!=)/gm);
foreach my $t (@tokens) {
# if the current token $t is one of our known functions
# then add it to %contains{$f}
if (defined($funcs{$t})) {
$contains{$f}->{$t} = 1;
};
};
};
my %out = %find;
# Iterate over each function's name. Add the name to %out
# and %find if it is called from within a wanted function.
# Repeat until %out doesn't change.
my %old_out;
do {
%old_out = %out;
foreach my $f (keys %find) {
foreach my $t (keys %{ $contains{$f} }) {
$out{$t} = 1; # add to output hash
$find{$t} = 1; # add to list of function names to search for
};
};
} until %out == %old_out;
# print the functions listed in %out, sorted by name
# otherwise will be printed in pseudo-random order as hashes
# are un-ordered.
foreach my $f (sort keys %out) {
print $funcs{$f}, "\n";
};
另存为,例如extract-funcs.pl
,使可执行文件chmod +x
像这样运行(带有函数定义的副本functions.txt
):
$ ./extract-funcs.pl functions.txt f1
f1() {
...
}
f1
不包含对其他函数的任何调用,因此仅打印 f1。
$ ./extract-funcs.pl functions.txt f2
f1() {
...
}
f2() {
f1
...
}
f2
包含对 f1 的调用,因此打印 f1 和 f2。
$ ./extract-funcs.pl functions.txt f4
f1() {
...
}
f2() {
f1
...
}
f3() {
f2
...
}
f4() {
f1
f3
...
}
f4
包含对 f1 和 f3 的调用,f3 包含对 f2 的调用,f2 包含对 f1 的调用,因此打印 f1、f2、f3 和 f4。 f1 仅打印一次,即使它是从 f4 和 f2 调用的
您可以通过管道将输出xsel -i -b
复制到剪贴板,以便与“编辑”菜单中的“粘贴”或Ctrl-V或Shift-一起使用Ins。或者只是xsel -i
复制到 X 的主要选择以进行中键粘贴。看man xsel
。