bash 脚本正则表达式将目录路径提升到第 n 级
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3790101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash script regex to get directory path up nth levels
提问by Steve
I'm using PWD to get the present working directory. Is there a SED or regex that I can use to, say, get the full path two parents up?
我正在使用 PWD 来获取当前的工作目录。是否有 SED 或正则表达式可以用来,例如,获取两个父母的完整路径?
回答by Bert F
Why sed or regex? Why not dirname:
为什么是 sed 或正则表达式?为什么不dirname:
parent=`dirname $PWD`
grandparent=`dirname $parent`
Edit:
编辑:
@Daentyh points out in the comments that apparently $()is preferred over backquotes ``for command substitution in POSIX-compliant shells. I don't have experience with them. More info:
@Daentyh 在评论中指出,在符合 POSIX 的 shell 中,命令替换显然$()比反引号更受欢迎``。我对他们没有经验。更多信息:
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03
So, if this applies to your shell, you can (should?) use:
因此,如果这适用于您的 shell,您可以(应该?)使用:
parent=$(dirname $PWD)
grandparent=$(dirname $parent)
回答by Paused until further notice.
This should work in POSIX shells:
这应该适用于 POSIX shell:
echo ${PWD%/*/*}
which will give you an absolute path rather than a relative one.
这将为您提供绝对路径而不是相对路径。
Also, see my answer herewhere I give two functions:
cdn () { pushd .; for ((i=1; i<=; i++)); do cd ..; done; pwd; }
which goes up nlevels given nas an argument.
给定n作为参数,它上升了n 个级别。
And:
和:
cdu () { cd "${PWD%//*}/"; }
which goes up to a named subdirectory above the current working directory.
它上升到当前工作目录上方的命名子目录。
回答by Benoit
why not use
为什么不使用
"${PWD}/../.."
?
?
回答by rubicks
Not sed or regex, but this does do arbitrary parent quantity:
不是 sed 或正则表达式,但这确实可以执行任意父数量:
$ 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
In this example, I cdinto a 5-deep temporary directory, assign n=3, construct a relative path nlevels up from ${PWD}, and -f, --canonicalizethe result with readlink.
在这个例子中,我cd到一个5级深度临时目录,分配n=3,构建一个相对路径n水平高达从${PWD},和-f, --canonicalize其结果readlink。
回答by noabody
Here's the regex that works for me. It's a little different between grep and Perl/sed:
这是对我有用的正则表达式。grep 和 Perl/sed 之间有点不同:
The extended regex breaks up paths into 0 or more groups of /ABC123anchored to the end of line, essentially working backward. (.*)consumes everything prior to this match and replaces it.
扩展的正则表达式将路径分解为 0 个或多个/ABC123锚定到行尾的组,基本上是向后工作。 (.*)消耗此匹配之前的所有内容并替换它。
user@home:~/adir/bdir$ pwd
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | perl -pe 's|(.*)((/.*?){0})$||'
/home/user/adir/bdir
user@home:~/adir/bdir$ pwd | perl -pe 's|(.*)((/.*?){1})$||'
/home/user/adir
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){2})$||'
/home/user
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){3})$||'
/home
user@home:~/adir/bdir$ pwd | sed -r 's|(.*)((/.*?){4})$||'
Grep can simulate substitution using a positive look ahead (?=which tells grep to match everything except the pattern. -Potells grep to use Perl regex and show only the match.
Grep 可以使用正向预测来模拟替换,(?=它告诉 grep 匹配除模式之外的所有内容。 -Po告诉 grep 使用 Perl 正则表达式并仅显示匹配项。
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})$)'
Of course it works equally well for Windows style paths:
当然,它同样适用于 Windows 风格的路径:
C:\home\user\adir\bdir> cd
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | perl -pe 's|(.*)((\.*?){0})$||'
C:\home\user\adir\bdir
C:\home\user\adir\bdir> cd | sed -r 's|(.*)((\.*?){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:
Sorry for the edits but I've been working on this enigma for about 16 hours now. Just kept trying different permutations and re-reading the regex docs. It had to sink in eventually.
抱歉进行了编辑,但我已经研究这个谜团大约 16 个小时了。只是不断尝试不同的排列并重新阅读正则表达式文档。它最终不得不沉入水中。

