Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash脚本regex将目录路径提升到第n个级别_Regex_Bash_Sed - Fatal编程技术网

bash脚本regex将目录路径提升到第n个级别

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}/../..

我正在使用PWD获取当前的工作目录。是否有一个SED或regex,我可以用来,比方说,获得双亲的完整路径?

为什么是SED或regex?为什么不
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: