bash:获得第n列输出的最短路径

时间:2011-09-06 06:13:17

标签: bash awk

假设您在工作日期间反复遇到bash中某些命令的以下形式的列化输出(在我的情况下,在我的Rails工作目录中执行svn st):

?       changes.patch
M       app/models/superman.rb
A       app/models/superwoman.rb

为了使用命令的输出 - 在这种情况下是文件名 - 需要某种解析,以便第二列可以用作下一个命令的输入。

我一直在做的是使用awk来获取第二列,例如当我想删除所有文件(不是那个典型的用例:)时,我会这样做:

svn st | awk '{print $2}' | xargs rm

由于我输入了很多内容,一个自然的问题是:在bash中有没有更短(更酷)的方法来实现这一点?

注意: 我问的问题本质上是一个shell命令问题,即使我的具体例子是在我的svn工作流程上。如果您认为工作流程很愚蠢并建议另一种方法,我可能不会投票给您,但其他人可能会,因为这里的问题实际上是如何以最短的方式获得bash中的第n列命令输出。谢谢:))

8 个答案:

答案 0 :(得分:92)

您可以使用cut访问第二个字段:

cut -f2

编辑: 抱歉,没有意识到SVN在其输出中没有使用制表符,所以这有点无用。您可以为输出定制cut,但它有点脆弱 - 类似cut -c 10-会起作用,但具体值取决于您的设置。

另一种选择是:sed 's/.\s\+//'

答案 1 :(得分:80)

完成同样的事情:

svn st | awk '{print $2}' | xargs rm

只使用bash你可以使用:

svn st | while read a b; do rm "$b"; done

当然,它并不短,但效率更高,它可以正确处理文件名中的空格。

答案 2 :(得分:25)

我发现自己处于相同的情况,最后将这些别名添加到我的.profile文件中:

alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"

这让我可以这样写:

svn st | c2 | xargs rm

答案 3 :(得分:14)

试试zsh。它支持后缀别名,因此您可以将.zshrc中的X定义为

alias -g X="| cut -d' ' -f2"

然后你可以这样做:

cat file X

您可以更进一步,为第n列定义它:

alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"

将输出文件“file”的第n列。您也可以为grep输出或更少的输出执行此操作。这非常方便,是zsh的杀手级功能。

您可以更进一步,将D定义为:

alias -g D="|xargs rm"

现在您可以输入:

cat file X1 D

删除文件“file”第一列中提到的所有文件。

如果您知道bash,除了一些新功能之外,zsh并没有太大的变化。

HTH Chris

答案 4 :(得分:7)

因为您似乎不熟悉脚本,所以这是一个例子。

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

如果您将其保存在~/bin/x中并确保~/bin在您的PATH中(现在这是您可以并且应该放在.bashrc中),那么您拥有通常提取列n的最短可能命令; x n。

如果使用非数字参数或不正确数量的参数调用等,脚本应该进行适当的错误检查和保释;但扩展到这个基本的必备版本将在102单元。

也许您会希望扩展脚本以允许不同的列分隔符。默认情况下,awk将输入解析为空格上的字段;要使用不同的分隔符,请使用-F ':',其中:是新的分隔符。将此作为脚本的一个选项实现会使它稍长一些,所以我将其留作读者的练习。


用法

给定文件file

1 2 3
4 5 6

你可以通过stdin传递它(仅使用useless cat作为占位符来获得更有用的东西);

$ cat file | sh script.sh 2
2
5

或者将其作为脚本的参数提供:

$ sh script.sh 2 file
2
5

这里,sh script.sh假设脚本在当前目录中保存为script.sh;如果您在PATH中的某个地方使用更有用的名称保存它并将其标记为可执行文件,如上面的说明中所示,显然请使用有用的名称(而不是sh)。

答案 5 :(得分:4)

看起来你已经有了解决方案。为了简化操作,为什么不将命令放在一个bash脚本(短名称)中,然后运行它而不是每次都输入'long'命令?

答案 6 :(得分:2)

如果您可以手动选择列,则使用pick

可以非常快
svn st | pick | xargs rm

只需转到第二列的任何单元格,按c,然后点击enter

答案 7 :(得分:1)

注意,该文件路径不必位于svn st输出的第二列。例如,如果修改文件并修改它的属性,它将是第3列。

请参阅:

中的可能输出示例
svn help st

示例输出:

 M     wc/bar.c
A  +   wc/qax.c

我建议通过以下方式剪切前8个字符:

svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done

如果你想100%确定,并在最后处理带有空格的花哨文件名,你需要解析xml输出:

svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'

当然,您可能希望使用一些真正的XML解析器而不是grep / sed。