编辑3:
虽然还不是严格的POSIX,但realpath自2012年起就是GNU核心应用程序。充分披露:在我注意到它后从未听说过它在info coreutils
TOC中,并立即想到了这个问题,但使用以下函数所示的方法应该可靠(很快就会成为POSIX标准?),而且希望能够高效地提供其调用者绝对来源的$0
:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath -s "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
编辑4: 值得注意的是,此解决方案使用POSIX参数扩展来首先检查路径是否需要扩展和解析,然后再尝试进行扩展和解析。这应该能够以我能想象到的最高效的方式返回一个绝对源$0
通过一个信使变量(值得注意的是,-s
将保留符号链接),无论路径是否已经是绝对路径。
编辑2:
现在我相信我更好地理解了你的问题,不幸的是,这实际上使下面大部分内容都不相关了。
(小修改:在找到文档中的realpath
之前,我至少将我的版本简化为不依赖时间字段,但是,公平警告,在测试一些之后,我不太确信ps
在其命令路径扩展能力方面完全可靠)
另一方面,你可以这样做:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
我需要修复它,使其更好地与字段配合使用,而不是只期望时间字段出现在进程路径之前,并依靠其包含的冒号作为参考,特别是因为这将无法处理您进程路径中的冒号,但我认为这是微不足道的并且很快就会发生。我相信该功能在其他方面符合POSIX标准。我认为仅参数扩展就可以做到必要的事情。
不太相关(或不正确):
这应该适用于符合POSIX指南的每种情况:
echo ${0%/*}
编辑:
我要承认,至少乍一看,我并不完全理解您描述的问题。显然,在您的问题中,您展示了一些关于通过参数扩展进行变量字符串操作的 POSIX 标准的熟悉度(即使您的特定实现在一瞥之间似乎有点紧张),所以我可能在我的问题解释中错过了一些重要信息,也许,至少在目前的形式下,这不是您寻求的答案。
我之前发布过有关内联变量空/设置测试的参数扩展,您可以在“Portable Way to Check Emptiness of a Shell Variable”问题中查看,这可能对您有用。我之所以提到这一点,主要是因为我的答案很大程度上是从 POSIX 参数扩展指南中复制/粘贴的,包括一个锚定链接,指向该主题的指南覆盖范围,并且包括一些来自经典文档和我自己构建的可能不太专业的示例。
然而,我自由地承认,虽然我还没有完全理解您的问题,但我不认为您会在那里找到具体的答案。相反,我怀疑您可能已经忘记了(就像我偶尔一样),即 POSIX 字符串操作中的 # 和 % 运算符用于指定要删除的字符串部分,而不是您希望保留的部分,这可能更直观。我的意思是,您以这种方式搜索的任何字符串片段都旨在从输出中消失,然后仅剩下您指定的搜索字符串被删除后原始字符串的剩余部分。
因此,以下是一些概述:
单个运算符将仅尽可能少地删除满足您搜索的内容,但是当双重运算符出现时,搜索将以贪婪形式进行,并且将尽可能多地删除原始字符串的内容。
除此之外,您只需要了解一些基本的正则表达式,并记住 # 从左侧开始搜索您要删除的字符串,并向右扫描,而 % 则从右侧开始搜索并向左扫描。
% _path_one='/one/two/three/four.five'
% _path_two='./four.five'
% echo ${_path_one%.*} ${_path_one%/*}
/one/two/three/four /one/two/three
% echo ${_path_one##*.} ${_path_one##*/}
five four.five
.
表示它可以无缝运行:这是一个有效的相对路径名。如果在其前面添加$PWD,则变成一个有效的非规范化绝对路径名:/home/me/.
更复杂但仍然正确的例子:/home/me/project1/../../../opt/freeware/bin
你真正的问题似乎是“如何将路径名转换为绝对路径并处于规范化形式?” - kubanczyksh
中$0
的定义。请参阅标题和正文。 - gavenkoabash
没有执行PATH
查找?"may" 意味着该命令可能是 shell 内置或函数。请阅读你引用链接中的解决过程。 - chepnercd /tmp; sh ls
- 失败并显示sh: 0: Can't open ls
... - gavenkoacd /tmp; sh -c 'ls'
- jackr