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

比方说,在你的工作date间,你反复遇到以下forms的列表输出(在我的Rails工作目录中执行svn st ):

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

为了处理命令的输出 – 在这种情况下是文件名 – 需要进行某种parsing,以便第二列可以用作下一个命令的input。

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

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

由于我input了很多,所以一个自然的问题是:在bash中是否有一个更短的(因此更酷)的方式来完成这个任务?

注:我所要求的实质上是一个shell命令的问题,即使我的具体例子是在我的svn工作stream程。 如果你觉得工作stream是愚蠢的,并build议一种替代方法,我可能不会投票给你,但其他人可能,因为这里的问题是真正如何获得第b列中的第n列命令输出,以尽可能最短的方式。 谢谢 :)

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

 cut -f2 

编辑:对不起,没有意识到SVN在其输出中不使用制表符,所以这是没有用的。 你可以裁剪输出,但有点脆弱 – 像cut -c 10-这样的东西可以工作,但确切的价值取决于你的设置。

另一个选项是这样的: sed 's/.\s\+//'

要完成同样的事情:

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

只使用bash你可以使用:

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

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

试试zsh。 它支持后缀别名,所以你可以在你的.zshrc中定义X.

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

那么你可以这样做:

猫文件X

您可以进一步将其定义为第n列:

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

这将输出文件“文件”的第n列。 你可以这样做,grep输出或更less的输出。 这非常方便,是zsh的杀手锏。

您可以进一步将D定义为别名-g D =“| xargs rm”

现在你可以input猫文件X1 D

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

如果你知道这个bash,除了一些新的function,zsh并不是什么大的变化。

HTH克里斯

我发现自己在相同的情况下,最终将这些别名添加到我的.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 

看起来你已经有了一个解决scheme。 为了使事情变得简单,为什么不把命令放在一个bash脚本(简称)中,而只是运行它,而不是每次input“long”命令?

因为你似乎不熟悉脚本,这里是一个例子。

 #!/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默认分析input到空白字段; 要使用不同的分隔符,请使用-F ':'其中:是新的分隔符。 实现这个作为脚本的一个选项使它稍长一点,所以我把它作为读者的一个练习。


用法

给定一个文件file

 1 2 3 4 5 6 

你可以通过标准input(使用无用的cat只是作为一个更有用的东西占位符);

 $ cat file | sh script.sh 2 2 5 

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

 $ sh script.sh 2 file 2 5 

在这里, sh script.sh假设脚本被保存为当前目录下的script.sh ; 如果你在PATH某个地方用一个更有用的名字来保存它,并且把它标记为可执行的,就像上面的说明一样,显然使用这个有用的名字(而不是sh )。

请注意,该文件path不必在svn st输出的第二列。 例如,如果您修改文件,并修改它的属性,它将是第3列。

查看可能的输出示例:

 svn help st 

示例输出:

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

我build议削减前8个字符:

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

如果你想100%确定,例如最后用空格处理花哨的文件名,你需要parsingxml输出:

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

当然,你可能想使用一些真正的XMLparsing器而不是grep / sed。

如果您可以手动select列,那么使用pick可以非常快速:

 svn st | pick | xargs rm 

只要去第二列的任何单元格,按c ,然后按enter