Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash:获取第n列输出的最短方法_Bash_Awk - Fatal编程技术网

bash:获取第n列输出的最短方法

bash:获取第n列输出的最短方法,bash,awk,Bash,Awk,假设在您的工作日中,您反复遇到bash中某个命令的以下列化输出形式(在我的例子中,是在Rails工作目录中执行svn st): 为了处理命令的输出(在本例中为文件名),需要进行某种解析,以便第二列可以用作下一个命令的输入 我一直在做的是使用awk获取第二列,例如,当我想删除所有文件时(不是典型的用例),我会: svn st | awk '{print $2}' | xargs rm 由于我经常输入这个,一个自然的问题是:在bash中是否有一种更短(因此更酷)的方法来实现这一点 注: 我问的基本

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

为了处理命令的输出(在本例中为文件名),需要进行某种解析,以便第二列可以用作下一个命令的输入

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

svn st | awk '{print $2}' | xargs rm
由于我经常输入这个,一个自然的问题是:在bash中是否有一种更短(因此更酷)的方法来实现这一点

注:
我问的基本上是一个shell命令问题,尽管我的具体示例是关于我的svn工作流的。如果您觉得工作流很愚蠢,并提出了另一种方法,我可能不会投您的反对票,但其他人可能会投您的反对票,因为这里的问题实际上是如何以尽可能最短的方式在bash中获得第n列命令输出。谢谢:)

看起来您已经有了解决方案。为了让事情变得更简单,为什么不将命令放在bash脚本中(用一个简短的名称),然后运行它,而不是每次都键入“long”命令?

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

cut -f2
编辑: 抱歉,我没有意识到SVN在输出中没有使用制表符,所以这有点没用。您可以根据输出量定制
cut
,但它有点脆弱-类似
cut-c10-
的功能可以工作,但具体值取决于您的设置


另一个选项类似于:
sed's/\s\+/'

试试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
删除文件“文件”第一列中提到的所有文件

如果您了解bash,那么除了一些新特性之外,zsh并没有太大的变化


HTH Chris

完成与以下相同的任务:

svn st | awk '{print $2}' | xargs rm
仅使用bash可以使用:

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

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

因为您似乎不熟悉脚本,下面是一个示例

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"
如果您将其保存在
~/bin/x
中,并确保
~/bin
位于您的
路径中(现在这是您可以并且应该放在
.bashrc
中的内容),则可以使用尽可能短的命令来提取列n;x n

如果使用非数值参数或参数数量不正确等调用,脚本应进行适当的错误检查和bail;但在102单元中,我们将对这个基本版本进行扩展

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


用法 给定一个文件
文件

1 2 3
4 5 6
您可以通过stdin传递它(仅将a用作更有用的内容的占位符)

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

$ sh script.sh 2 file
2
5

这里,
sh script.sh
假设脚本保存为当前目录中的
script.sh
;如果在
路径
中的某个位置使用更有用的名称保存它,并将其标记为可执行,如上面的说明所示,显然应使用有用的名称(并且不使用
sh
)。

注意,该文件路径不必位于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。

如果您可以手动选择列,则可以非常快速地使用:


只需转到第二列的任何单元格,按
c
,然后点击
enter
我发现自己也处于同样的情况,并最终将这些别名添加到我的
档案中

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

当您经常使用命令时,您最好创建一个脚本并将其放在您的路径中。如果您愿意,您可以在bashrc中创建一个函数。我看不出减少列选择表达式的意义。你是对的,我可能会这样做。“重点”是寻求在bash中做事情的新方法,目的是为了学习,但主要是为了好玩:)另外,当ssh在某个地方运行时,你没有.bashrc,因此了解没有它的情况很有用。啊,我看到你在上面键入我的评论时更新了答案:)你能动态指定要获取的列吗,或者我的.zshrc中需要n行(这并不重要,只是好奇)我已经进一步编辑了我的帖子,并定义了一个后缀“D”来删除文件。据我所知,您必须为每个后缀添加一行。或者将其作为X命令的第一个参数。所有这些都不需要zsh或别名,除了在别名中插入管道的特殊想法。我不明白为什么你们都喜欢
cut
选项。使用
svn st
的输出,它在我的机器上根本不工作。尝试
svn st | cut-d'-f2
看看会发生什么。@Sv1您可以编写
svn st | pick | xargs rm
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