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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:41:34  来源:igfitidea点击:

bash script regex to get directory path up nth levels

regexbashsed

提问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 个小时了。只是不断尝试不同的排列并重新阅读正则表达式文档。它最终不得不沉入水中。