bash脚本regex将目录路径提升到第n个级别
我正在使用PWD获取当前的工作目录。是否有一个SED或regex,我可以用来,比方说,获得双亲的完整路径?为什么是SED或regex?为什么不bash脚本regex将目录路径提升到第n个级别,regex,bash,sed,Regex,Bash,Sed,我正在使用PWD获取当前的工作目录。是否有一个SED或regex,我可以用来,比方说,获得双亲的完整路径?为什么是SED或regex?为什么不dirname: parent=`dirname $PWD` grandparent=`dirname $parent` 编辑: @Daenthy在评论中指出,对于POSIX兼容shell中的命令替换,显然$()优于反引号`。我对他们没有经验。更多信息: 因此,如果这适用于您的shell,您可以(应该?)使用: 为什么不使用 "${PWD}/../..
dirname
:
parent=`dirname $PWD`
grandparent=`dirname $parent`
编辑:
@Daenthy在评论中指出,对于POSIX兼容shell中的命令替换,显然$()
优于反引号`
。我对他们没有经验。更多信息:
因此,如果这适用于您的shell,您可以(应该?)使用:
为什么不使用
"${PWD}/../.."
?这应该适用于POSIX外壳:
echo ${PWD%/*/*}
这会给你一条绝对路径,而不是相对路径
另外,请参见我的答案,其中我给出了两个函数:
cdn () { pushd .; for ((i=1; i<=$1; i++)); do cd ..; done; pwd; }
它会上升到当前工作目录上方的一个命名子目录。不是sed或regex,但它会执行任意父目录数量:
$ cd $(mktemp -dp $(mktemp -dp $(mktemp -dp $(mktemp -d)))) && \
> n=3 && \
> readlink -f ${PWD}/$(for i in $(seq ${n}); do echo -n '../' ; done)
/tmp/tmp.epGcUeLV9q
在本例中,我将
cd
放入一个5深的临时目录中,分配n=3
,从${PWD}
层次上构造一个相对路径n
,并用readlink
规范化结果。grep和Perl/sed之间有点不同:
扩展正则表达式将路径分解为0个或多个锚定到行尾的/ABC123
组,基本上是向后工作的<代码>(*)使用此匹配之前的所有内容并替换它
user@home:~/adir/bdir$ pwd
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | perl -pe 's|(.*)((/.*?){0})$|\1|'
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | perl -pe 's|(.*)((/.*?){1})$|\1|'
/home/user/adir
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){2})$|\1|'
/home/user
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){3})$|\1|'
/home
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){4})$|\1|'
Grep可以使用正向前瞻(?=
来模拟替换,它告诉Grep匹配除模式之外的所有内容。-Po
告诉Grep使用Perl regex并仅显示匹配项
user@home:~/adir/bdir$ pwd
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){0})$)'
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){1})$)'
/home/user/adir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){2})$)'
/home/user
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){3})$)'
/home
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){4})$)'
当然,它同样适用于Windows样式的路径:
C:\home\user\adir\bdir> cd
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | perl -pe 's|(.*)((\\.*?){0})$|\1|'
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | sed -r 's|(.*)((\\.*?){1})$|\1|'
C:\home\user\adir
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){2})$)'
C:\home\user
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){3})$)'
C:\home
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){4})$)'
C:
很抱歉编辑,但我已经为这个谜工作了大约16个小时。只是不断尝试不同的排列并重新阅读正则表达式文档。它最终不得不被理解。你应该使用
$()
而不是`
,因为他指定了bash。@daynyth-是的,我实际上在考虑建议他重新回答这个问题(或者请允许我重新标记)到sh
或shell脚本编写
,因为这个问题并不是真正的bash
具体问题。@Steve-你怎么看?即使如此,$()
仍然是POSIX sh。(虽然不是所有的sh都是POSIX)进一步的唠叨:你应该引用PWD作为“$PWD”
,否则目录名中的空格将使您崩溃。@尽管Benoit的解决方案简单得多,而且可以在任何地方正常工作。dirname
也不是完全可移植的。请注意,/foo
的祖父母将是
。这应该是答案。这比公认的答案更易于重用。
user@home:~/adir/bdir$ pwd
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){0})$)'
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){1})$)'
/home/user/adir
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){2})$)'
/home/user
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){3})$)'
/home
user@home:~/adir/bdir$ pwd | grep -Po '(.*)(?=((/.*?){4})$)'
C:\home\user\adir\bdir> cd
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | perl -pe 's|(.*)((\\.*?){0})$|\1|'
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | sed -r 's|(.*)((\\.*?){1})$|\1|'
C:\home\user\adir
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){2})$)'
C:\home\user
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){3})$)'
C:\home
C:\home\user\adir\bdir> cd | grep -Po '(.*)(?=((\\.*?){4})$)'
C: