【问题标题】:Strip double dots from path in bash从bash中的路径中去除双点
【发布时间】:2013-04-13 03:01:48
【问题描述】:

我想知道如何使用正则表达式来简化文件路径中的双点(路径可能实际上不存在)?

例如将/my/path/to/.././my/./../../file.txt 更改为/my/file.txt 或将path/./to/../../../file.txt 更改为../file.txt

是否可以在 bash 的一个命令中执行此操作? (例如使用sed,而不是复杂的python或perl脚本)

编辑:我遇到了this question,但realpath 在我使用的计算机上不可用。

编辑: 从F.J 的解决方案中,我最终构建了以下正则表达式,它适用于更一般的情况(如果路径的某些文件夹名为....,则不起作用):

sed -e 's|/\./|/|g' -e ':a' -e 's|\.\./\.\./|../..../|g' -e 's|^[^/]*/\.\.\/||' -e 't a' -e 's|/[^/]*/\.\.\/|/|' -e 't a' -e 's|\.\.\.\./|../|g' -e 't a'

【问题讨论】:

  • realpath 命令不可用,还是realpath() 功能不可用?如果你有这个功能,一个合适的程序是:#define _XOPEN_SOURCE 600#include <limits.h>#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv) { int rc = 0; for (int i = 1; i < argc; i++) { char realname[_POSIX_PATH_MAX]; if (realpath(argv[i], realname) != 0) printf("%s\n", realname); else { fprintf(stderr, "Failed to evaluate realpath for %s\n", argv[i]); rc = 1; } } return(rc); }
  • 只有realpath 命令不可用。但是,我想在可再发行的 bash 脚本中使用它,这使得这个解决方案不是很方便。还是谢谢。

标签: regex bash path sed


【解决方案1】:

尝试以下方法:

sed -e 's|/\./|/|g' -e ':a' -e 's|/[^/]*/\.\./|/|' -e 't a'

例子:

$ echo '/my/path/to/.././my/./../../file.txt' |
  sed -e 's|/\./|/|g' -e ':a' -e 's|/[^/]*/\.\./|/|' -e 't a'
/my/file.txt

以下是该方法的说明:

read line
replace all '/\./' in line with '/'
while there is a match of '/[^/]*/\.\./' {
    replace first occurrence of '/[^/]*/\.\./' in line with '/'
}
output line

【讨论】:

  • 我最终使用了以下命令,如果路径应以 ../ 开头:sed -e 's|/\./|/|g' -e ':a' -e 's|/[^/]*/\.\./|/|' -e 't a' -e 's|^[^/]*/\.\./|../|' 也可以使用。谢谢。
  • 为什么不这样:sed -e 's|/\./|/|g' -e ':a' -e 's|[^/]+/\.\./|/|' -e 't a' 工作?
  • @Mat 可能是+,试试改成\+
  • @Mat:标准 (POSIX) sed 不理解 + 表示法。一些(可能很多)版本的sed 识别选项-r 以使用扩展正则表达式,其中+| 等被识别。检查系统上的手册页。
  • 你方法的问题是最终将../../ 减少到零。我在我的问题中提出了一个解决方案来防止这种情况发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
相关资源
最近更新 更多