假设输入参数是几个文件的FULL路径.说,
/abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3
>如何在bash shell脚本中获取目录名/ abc / def?
>我怎样才能获得file1,/ ghi / file2和/ ghi / file3?
鉴于第1部分(公共前缀)的答案,第2部分的答案是直截了当的;你将每个名字的前缀切掉,这可以用sed和其他选项完成.
然后,有趣的部分是找到共同的前缀.最小公共前缀是/(例如,对于/ etc / passwd和/ bin / sh).最大公共前缀(根据定义)存在于所有字符串中,因此我们只需将其中一个字符串拆分为段,并将可能的前缀与其他字符串进行比较.概述:
split name A into components known_prefix="/" for each extra component from A do possible_prefix="$known_prefix/$extra/" for each name do if $possible_prefix is not a prefix of $name then ...all done...break outer loop... fi done ...got here...possible prefix is a prefix! known_prefix=$possible_prefix done
有一些管理细节要处理,例如名称中的空格.还有什么是允许的武器.问题是标记为bash但允许哪些外部命令(例如Perl)?
一个未定义的问题 – 假设名称列表是:
/abc/def/ghi /abc/def/ghi/jkl /abc/def/ghi/mno
是最长的共同前缀/ abc / def还是/ abc / def / ghi?我假设这里最长的公共前缀是/ abc / def. (如果你真的希望它是/ abc / def / ghi,那么使用/ abc / def / ghi /.作为第一个名字.)
此外,还有调用详细信息:
>如何调用此函数或命令?
>如何返回值?
>这是一个或两个函数或命令(longest_common_prefix和’path_without_prefix`)?
两个命令更容易:
> prefix = $(longest_common_prefix name1 [name2 …])
> suffix = $(path_without_prefix / pre / fix / pre / fix / to / file […])
path_without_prefix命令会删除前缀(如果存在),如果前缀未启动名称,则保留参数不变.
longest_common_prefix
longest_common_prefix() { declare -a names declare -a parts declare i=0 names=("$@") name="$1" while x=$(dirname "$name"); [ "$x" != "/" ] do parts[$i]="$x" i=$(($i + 1)) name="$x" done for prefix in "${parts[@]}" / do for name in "${names[@]}" do if [ "${name#$prefix/}" = "${name}" ] then continue 2 fi done echo "$prefix" break done }
测试:
set -- "/abc/def/file 0" /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 "/abc/def/ghi/file 4" echo "Test: $@" longest_common_prefix "$@" echo "Test: $@" abc/def longest_common_prefix "$@" abc/def set -- /abc/def/ghi/jkl /abc/def/ghi /abc/def/ghi/mno echo "Test: $@" longest_common_prefix "$@" set -- /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 echo "Test: $@" longest_common_prefix "$@" set -- "/a c/d f/file1" "/a c/d f/ghi/file2" "/a c/d f/ghi/file3" echo "Test: $@" longest_common_prefix "$@"
输出:
Test: /abc/def/file 0 /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 /abc/def/ghi/file 4 /abc/def Test: /abc/def/file 0 /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 /abc/def/ghi/file 4 abc/def Test: /abc/def/ghi/jkl /abc/def/ghi /abc/def/ghi/mno /abc/def Test: /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 /abc/def Test: /a c/d f/file1 /a c/d f/ghi/file2 /a c/d f/ghi/file3 /a c/d f
path_without_prefix
path_without_prefix() { local prefix="$1/" shift local arg for arg in "$@" do echo "${arg#$prefix}" done }
测试:
for name in /pre/fix/abc /pre/fix/def/ghi /usr/bin/sh do path_without_prefix /pre/fix $name done
输出:
abc def/ghi /usr/bin/sh