获得输出的第 n 列的最短方法是什么?
假设在工作日期间,您反复遇到 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 工作流程。
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):
? 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:
svn st | awk '{print $2}' | xargs rm
Since I type this a lot, a natural question is: is there a shorter (thus cooler) way of accomplishing this in bash?
What I am asking is essentially a shell command question even though my concrete example is on my svn workflow.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您可以使用
cut
来访问第二个字段:编辑:
抱歉,我没有意识到 SVN 在其输出中不使用制表符,所以这有点没用。您可以根据输出定制
cut
,但它有点脆弱 - 像cut -c 10-
这样的东西可以工作,但确切的值将取决于您的设置。另一种选择类似于:
sed 's/.\s\+//'
You can use
cut
to access the second field: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 likecut -c 10-
would work, but the exact value will depend on your setup.Another option is something like:
sed 's/.\s\+//'
要完成与以下相同的事情:
仅使用 bash 您可以使用:
当然,它并不短,但它更有效,并且它可以正确处理文件名中的空格。
To accomplish the same thing as:
using only bash you can use:
Granted, it's not shorter, but it's a bit more efficient and it handles whitespace in your filenames correctly.
我发现自己处于同样的情况,最终将这些别名添加到我的
.profile
文件中:这允许我编写如下内容:
I found myself in the same situation and ended up adding these aliases to my
.profile
file:Which allows me to write things like this:
尝试一下 zsh。它支持后缀别名,因此您可以在 .zshrc 中定义 X
,然后您可以执行以下操作:
您可以更进一步,为第 n 列定义它:
这将输出文件“file”的第 n 列。您也可以对 grep 输出或 less 输出执行此操作。这是非常方便的,也是 zsh 的杀手级功能。
您可以更进一步,将 D 定义为:
现在您可以键入:
删除文件“file”第一列中提到的所有文件。
如果您了解 bash,那么除了一些新功能外,zsh 并没有太大变化。
克里斯·HTH
Try the zsh. It supports suffix alias, so you can define X in your .zshrc to be
then you can do:
You can take it one step further and define it for the nth column:
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.
You can go one step further and define D to be:
Now you can type:
to delete all files mentioned in the first column of file "file".
If you know the bash, the zsh is not much of a change except for some new features.
HTH Chris
因为你似乎对脚本不熟悉,这里举一个例子。
如果您将其保存在
~/bin/x
中,并确保~/bin
位于您的PATH
中(现在您可以并且应该这么做)放入您的.bashrc
中),您将拥有用于一般提取第 n 列的最短命令; x n。如果使用非数字参数或不正确的参数数量等调用,脚本应该进行适当的错误检查和保释;但对这个最基本的基本版本的扩展将在单元 102 中进行。
也许您会想要扩展脚本以允许使用不同的列分隔符。默认情况下,awk 将输入解析为空白字段;要使用不同的分隔符,请使用
-F ':'
,其中:
是新的分隔符。将其作为脚本的一个选项来实现会使其稍微长一些,因此我将其作为练习留给读者。用法
给定一个文件
file
:您可以通过 stdin 传递它(使用 无用的
cat
只是作为更有用的内容的占位符);或者将其作为脚本的参数提供:
这里,
sh script.sh
假设脚本在当前目录中保存为script.sh
;如果您使用更有用的名称将其保存在PATH
中的某个位置并将其标记为可执行文件,如上面的说明所示,显然请使用有用的名称(而不是sh
)。在上面的示例中,我将其命名为x
只是为了制定最短的解决方案。Because you seem to be unfamiliar with scripts, here is an example.
If you save this in
~/bin/x
and make sure~/bin
is in yourPATH
(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.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.
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.Usage
Given a file
file
:You can either pass it via stdin (using a useless
cat
merely as a placeholder for something more useful);Or provide it as an argument to the script:
Here,
sh script.sh
is assuming that the script is saved asscript.sh
in the current directory; if you save it with a more useful name somewhere in yourPATH
and mark it executable, as in the instructions above, obviously use the useful name instead (and nosh
). In the example above, I called itx
just to make the shortest possible solution.看起来你已经有了解决方案。为了让事情变得更简单,为什么不将命令放入 bash 脚本(使用短名称)中并运行它,而不是每次都键入“长”命令?
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?
如果您可以手动选择列,那么使用 pick:
只需转到第二列的任意单元格,按
c
,然后按enter
If you are ok with manually selecting the column, you could be very fast using pick:
Just go to any cell of the 2nd column, press
c
and then hitenter
请注意,该文件路径不必位于 svn st 输出的第二列中。例如,如果您修改文件并修改其属性,它将是第三列。
请参阅以下可能的输出示例:
示例输出:
我建议通过以下方式剪切前 8 个字符:
如果您想 100% 确定,并处理末尾带有空格的奇特文件名,则需要解析 xml 输出:
当然您可能想使用一些真正的 XML 解析器而不是 grep/sed。
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.
See possible output examples in:
Example output:
I suggest to cut first 8 characters by:
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:
Of course you may want to use some real XML parser instead of grep/sed.