bash:获取第 n 列输出的最短方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7315587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash: shortest way to get n-th column of output
提问by Sv1
Let's say that during your workday you repeatedly encounter the following form of columnized output from some command in bash (in my case from executing svn st
in my Rails working directory):
假设在您的工作日期间,您反复遇到以下形式的来自 bash 中某些命令的列化输出(在我的情况下是svn st
在我的 Rails 工作目录中执行):
? changes.patch
M app/models/superman.rb
A app/models/superwoman.rb
in order to work with the output of your command - in this case the filenames - some sort of parsing is required so that the second column can be used as input for the next command.
为了处理您的命令的输出 - 在这种情况下是文件名 - 需要某种解析,以便第二列可以用作下一个命令的输入。
What I've been doing is to use awk
to get at the second column, e.g. when I want to remove all files (not that that's a typical usecase :), I would do:
我一直在做的是用来awk
获取第二列,例如,当我想删除所有文件时(这不是典型的用例:),我会这样做:
svn st | awk '{print }' | xargs rm
Since I type this a lot, a natural question is: is there a shorter (thus cooler) way of accomplishing this in bash?
由于我经常输入这些内容,一个自然的问题是:在 bash 中是否有更短(因此更酷)的方式来完成此任务?
NOTE: What I am asking is essentially a shell command question even though my concrete example is on my svn workflow. If you feel that workflow is silly and suggest an alternative approach, I probably won't vote you down, but others might, since the question here is really how to get the n-th column command output in bash, in the shortest manner possible. Thanks :)
注意:即使我的具体示例是在我的 svn 工作流程中,我所问的本质上也是一个 shell 命令问题。如果您觉得工作流程很愚蠢并建议采用替代方法,我可能不会投票给您,但其他人可能会投票,因为这里的问题实际上是如何以尽可能最短的方式在 bash 中获取第 n 列命令输出. 谢谢 :)
回答by porges
You can use cut
to access the second field:
您可以使用cut
访问第二个字段:
cut -f2
Edit:
Sorry, didn't realise that SVN doesn't use tabs in its output, so that's a bit useless. You can tailor cut
to the output but it's a bit fragile - something like cut -c 10-
would work, but the exact value will depend on your setup.
编辑:抱歉,没有意识到 SVN 在其输出中不使用制表符,所以这有点没用。您可以定制cut
输出,但它有点脆弱 - 类似的东西cut -c 10-
会起作用,但确切的值将取决于您的设置。
Another option is something like: sed 's/.\s\+//'
另一种选择是这样的: sed 's/.\s\+//'
回答by Rick Sladkey
To accomplish the same thing as:
要完成与以下相同的事情:
svn st | awk '{print }' | xargs rm
using only bash you can use:
只使用 bash 您可以使用:
svn st | while read a b; do rm "$b"; done
Granted, it's not shorter, but it's a bit more efficient and it handles whitespace in your filenames correctly.
当然,它不是更短,但它更有效一点,它可以正确处理文件名中的空格。
回答by StackedCrooked
I found myself in the same situation and ended up adding these aliases to my .profile
file:
我发现自己处于同样的情况并最终将这些别名添加到我的.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}'"
Which allows me to write things like this:
这让我可以写这样的东西:
svn st | c2 | xargs rm
回答by Chris
Try the zsh. It supports suffix alias, so you can define X in your .zshrc to be
试试zsh。它支持后缀别名,因此您可以在 .zshrc 中定义 X 为
alias -g X="| cut -d' ' -f2"
then you can do:
那么你可以这样做:
cat file X
You can take it one step further and define it for the nth column:
您可以更进一步,为第 n 列定义它:
alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"
which will output the nth column of file "file". You can do this for grep output or less output, too. This is very handy and a killer feature of the zsh.
这将输出文件“file”的第 n 列。您也可以为 grep 输出或更少的输出执行此操作。这非常方便,也是 zsh 的一个杀手级功能。
You can go one step further and define D to be:
您可以更进一步,将 D 定义为:
alias -g D="|xargs rm"
Now you can type:
现在你可以输入:
cat file X1 D
to delete all files mentioned in the first column of file "file".
删除文件“file”第一列中提到的所有文件。
If you know the bash, the zsh is not much of a change except for some new features.
如果您了解 bash,那么除了一些新功能外,zsh 没有太大变化。
HTH Chris
HTH克里斯
回答by tripleee
Because you seem to be unfamiliar with scripts, here is an example.
因为您似乎不熟悉脚本,所以这里有一个示例。
#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=
shift
awk -v col="$col" '{print $col}' "${@--}"
If you save this in ~/bin/x
and make sure ~/bin
is in your PATH
(now that is something you can and should put in your .bashrc
) you have the shortest possible command for generally extracting column n; x n.
如果您将其保存~/bin/x
并确保~/bin
在您的PATH
(现在这是您可以并且应该放入您的.bashrc
)中,您将拥有通常提取列 n 的最短命令;x n。
The script should do proper error checking and bail if invoked with a non-numeric argument or the incorrect number of arguments, etc; but expanding on this bare-bones essential version will be in unit 102.
如果使用非数字参数或不正确数量的参数等调用,脚本应该进行适当的错误检查和保释;但扩展这个基本的基本版本将在 102 单元中。
Maybe you will want to extend the script to allow a different column delimiter. Awk by default parses input into fields on whitespace; to use a different delimiter, use -F ':'
where :
is the new delimiter. Implementing this as an option to the script makes it slightly longer, so I'm leaving that as an exercise for the reader.
也许您想扩展脚本以允许使用不同的列分隔符。awk 默认将输入解析为空白字段;要使用不同的分隔符,请使用新的分隔符-F ':'
where :
。将它作为脚本的一个选项来实现它会稍微长一些,所以我把它留给读者作为练习。
Usage
用法
Given a file file
:
给定一个文件file
:
1 2 3
4 5 6
You can either pass it via stdin (using a useless cat
merely as a placeholder for something more useful);
您可以通过 stdin 传递它(使用无用的cat
只是作为更有用的东西的占位符);
$ cat file | sh script.sh 2
2
5
Or provide it as an argument to the script:
或者将其作为参数提供给脚本:
$ sh script.sh 2 file
2
5
Here, sh script.sh
is assuming that the script is saved as script.sh
in the current directory; if you save it with a more useful name somewhere in your PATH
and mark it executable, as in the instructions above, obviously use the useful name instead (and no sh
).
这里,sh script.sh
假设脚本保存script.sh
在当前目录中;如果您在某处使用更有用的名称保存它并将其PATH
标记为可执行,如上面的说明,显然使用有用的名称代替(而不是sh
)。
回答by Tarek Fadel
It looks like you already have a solution. To make things easier, why not just put your command in a bash script (with a short name) and just run that instead of typing out that 'long' command every time?
看起来您已经有了解决方案。为了让事情更简单,为什么不把你的命令放在一个 bash 脚本中(用一个短名称)然后运行它而不是每次都输入那个“长”命令?
回答by Bernardo Rufino
回答by Micha? ?rajer
Note, that file path does not have to be in second column of svn st output. For example if you modify file, and modify it's property, it will be 3rd column.
请注意,该文件路径不必在 svn st 输出的第二列中。例如,如果您修改文件,并修改它的属性,它将是第 3 列。
See possible output examples in:
请参阅以下可能的输出示例:
svn help st
Example output:
示例输出:
M wc/bar.c
A + wc/qax.c
I suggest to cut first 8 characters by:
我建议通过以下方式剪切前 8 个字符:
svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done
If you want to be 100% sure, and deal with fancy filenames with white space at the end for example, you need to parse xml output:
例如,如果您想 100% 确定,并处理末尾带有空格的花哨文件名,则需要解析 xml 输出:
svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'
Of course you may want to use some real XML parser instead of grep/sed.
当然,您可能想使用一些真正的 XML 解析器而不是 grep/sed。