假设您在工作日期间反复遇到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列命令输出。谢谢:))
答案 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)
答案 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。