如何使用 grep 输出作为 cd 的路径?

mic*_*imo 9 command-line bash directory grep

如何通过管道将grep输出作为cd命令的参数?

例如:

[root@xxx xxx]# pip install django | grep '/usr.*'  
Requirement already satisfied (use --upgrade to upgrade): django in   /usr/lib64/python2.7/site-packages
Run Code Online (Sandbox Code Playgroud)

这里/usr/lib64/python2.7/site-packages突出显示,我想将此字符串传递给cd.

hee*_*ayl 18

使用 Bash 的命令替换 $(),您还需要-o使用 grep 仅选择匹配的部分:

cd "$(pip install django | grep -o '/usr.*')"
Run Code Online (Sandbox Code Playgroud)

请注意,尽管在这种情况下您会逃脱,但您应该始终用双引号将命令替换括起来,以便 shell 不会对空格执行分(默认情况下,空格、制表符和换行符取决于 的IFS变量bash)。


Eli*_*gan 9

根据你做什么,不事先什么知道pip会输出,可以自行决定是否grep比其他的东西/usr.*

如果您知道目录以 开头/usr(并且它出现在 的输出行的末尾pip,并且/usr没有出现在目录名称之前的行中的任何位置),那么这是一个不错的选择;heemayl 的回答告诉你怎么做。

如果您知道它开头的原因/usr是您刚刚运行了命令并知道要更改的目录,我建议使用更简单的解决方案运行命令cd /usr/lib64/python2.7/site-packages。即使您不使用制表符完成,这也减少了打字次数。

否则,您可能会选择不同的正则表达式,具体取决于您对正在解析的输出的了解。下面的所有替代方案仍然假设目录名称出现在行尾,但其他假设有所不同。

如果您知道目录名称是绝对的(即以 a 开头/并且没有/出现在目录名称之前的行上,您可以使用与heemayl 的答案相同的正则表达式,但使用/代替/usr

cd "$(pip install django | grep -o '/.*')"
Run Code Online (Sandbox Code Playgroud)

这匹配 a/后跟零个或多个 ( *) 的任何字符 ( .)。

如果您知道目录名称不包含水平空白(没有空格或制表符)并且出现在行尾,则可以使用:

cd "$(pip install django | grep -oP '[^\h]+$')"
Run Code Online (Sandbox Code Playgroud)

在这里,我使用了 Perl regexp ( -P) 因为\h缩写 (for [:blank:]) 比等效的扩展 regexp ( -E)更易于键入和阅读。这匹配一个或多个 ( +) 一类字符 ( [ ]) 中不是( ^) 空格或制表符 ( \h)的任何字符。

如果你知道牛逼,他的目录名称是其前后通过in由水平空白包围(即,填充在左边,用空格右边两个),而这是唯一出现这样in就行了,你可以使用:

cd "$(pip install django | grep -oP '\hin\h+\K.+')"
Run Code Online (Sandbox Code Playgroud)

这将使用零宽度正向后看断言(\K)来匹配一个或多个字符(.+),空格或标签(之后出现\h),in和另外一个或多个空格或制表符(\h+),实际上并没有包括in和空格在比赛中围绕它。环视断言是 Perl 正则表达式的一个特性。

该模式也可以工作,但我们只需要在 之前寻找一个空白,无论存在多少。相反,我们必须匹配 之后的所有空格,否则它们不会被丢弃,而是作为目录名称的一部分进行匹配。\h+in\h+\K.+inin\K

如果您知道目录名称紧跟在该行最后一次出现的in后面跟有水平空白,则可以使用:

set +H
cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')"
set -H
Run Code Online (Sandbox Code Playgroud)

在那里,零宽度正后视断言本身包含一个零宽度负前瞻断言 ( (?! ))。

!以这样的方式为可出现难以逃脱优雅; 我用来防止它在传递给之前触发 shell历史扩展的方法grepset +H在运行命令之前暂时禁用历史扩展 ( ) 并在之后重新启用它 ( set -H)。如果您在脚本中使用它并且您的脚本不包含set -H,则无需执行此操作,因为仅当 shell 以交互方式运行时才会自动启用历史扩展。

最后,需要注意的是没有这些,也不heemayl的回答,实际上是管道输出grepcd(虽然输出pip仍然被输送到grep)。而不是管道,适合这项工作的工具是命令替换