如何使用grep输出作为cd的路径?
如何将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
这里突出显示/usr/lib64/python2.7/site-packages
,我想将此字符串传递给cd
。
使用Bash的命令替换 $()
,你还需要-o
和grep来只选择匹配的部分:
cd "$(pip install django | grep -o '/usr.*')"
请注意,虽然在这种情况下你会逃脱但是你应该总是用双引号括起命令替换,这样shell就不会在空格上执行分词 (默认空格,制表符和换行符,取决于bash
情况下的IFS
变量) )。
根据您所做的事情以及事先不知道pip
将输出的内容,您可能决定使用/usr.*
其他内容进行grep
。
如果你知道目录以/usr
开头 (并且它出现在pip
的输出行的末尾,并且/usr
没有出现在目录名之前的行的任何地方),那么这是一个很好的选择; heemayl的回答告诉你如何。
如果您知道它以/usr
开头的原因是您刚刚运行该命令并知道要更改的目录,我建议运行命令cd /usr/lib64/python2.7/site-packages
的更简单的解决方案。 即使您不使用制表符,也可以减少输入。
否则,您可能会选择不同的正则表达式,具体取决于您对正在解析的输出的了解。 下面的所有替代方案仍假设目录名称出现在行尾,但其他假设各不相同。
如果你知道目录名是绝对的 (即以/
开头) 并且在目录名之前的行上没有/
出现 ,你可以使用与heemayl的答案相同的正则表达式,但使用/
而不是/usr
:
cd "$(pip install django | grep -o '/.*')"
这匹配/
后跟任何字符( .
)的零或更多( *
)。
如果您知道目录名称不包含水平空格 (没有空格或制表符)并显示在该行的末尾,则可以使用:
cd "$(pip install django | grep -oP '[^\h]+$')"
这里我使用了Perl regexp ( -P
),因为\h
缩写(对于[:blank:]
)使得输入和读取比等效的扩展正则表达式( -E
)更容易。 这匹配不是 ( ^
)空格或制表符( \h
)的字符类( [
]
)中的任何字符的一个或多个( +
)。
如果您知道目录名称紧跟在水平空格的前面 (即左侧和右侧用空格填充),并且这是该行中唯一出现的这种情况 ,您可以使用:
cd "$(pip install django | grep -oP '\hin\h+\K.+')"
这使用零宽度正向后视断言( \K
)来匹配出现在空格或制表符( \h
)之后的一个或多个字符( .+
),以及另一个或多个空格或制表符( \h+
),实际上没有包括in
比赛中的围绕它的空白区域。 查找断言是Perl正则表达式的一个特性。
\h + in\h+\K.+
的模式\h + in\h+\K.+
也会起作用,但我们只需要在输入之前查找一个空白,无论存在多少空白。 相反,我们必须匹配in
之后的所有空格,否则它们不会被\K
丢弃,它们将作为目录名称的一部分进行匹配。
如果您知道目录名称后面紧跟着行的最后一次出现,后跟水平空格 ,则可以使用:
set +H cd "$(pip install django | grep -oP '\hin\h+(?!.*\hin\h.*)\K.*')" set -H
在那里,零宽度正面后置断言本身包含零宽度负向前瞻断言( (?!
)
)。
的!
以一种优雅地难以逃脱的方式出现; 我用来阻止它在传递给grep
之前触发shell 历史扩展的方法是在运行命令之前暂时禁用历史扩展( set +H
)并在之后重新启用它( set -H
)。 如果您在脚本中使用此脚本且脚本不包含set -H
,则不需要执行此操作,因为仅当shell以交互方式运行时才会自动启用历史记录扩展。
最后,请注意,这些都没有,也没有heemayl的答案 ,实际上是将grep
的输出传递给cd
(虽然pip
的输出仍然被传送到grep
)。 而不是管道 ,这个工作的适当工具是命令替换 。