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
)。
根据你做什么,不事先什么知道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.+
in
in
\K
如果您知道目录名称紧跟在该行最后一次出现的in
后面跟有水平空白,则可以使用:
set +H
cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')"
set -H
Run Code Online (Sandbox Code Playgroud)
在那里,零宽度正后视断言本身包含一个零宽度负前瞻断言 ( (?!
)
)。
在!
以这样的方式为可出现难以逃脱优雅; 我用来防止它在传递给之前触发 shell历史扩展的方法grep
是set +H
在运行命令之前暂时禁用历史扩展 ( ) 并在之后重新启用它 ( set -H
)。如果您在脚本中使用它并且您的脚本不包含set -H
,则无需执行此操作,因为仅当 shell 以交互方式运行时才会自动启用历史扩展。
最后,需要注意的是没有这些,也不heemayl的回答,实际上是管道输出grep
到cd
(虽然输出pip
仍然被输送到grep
)。而不是管道,适合这项工作的工具是命令替换。