367

我想使用空格作为cut命令的分隔符。

我可以为此使用什么语法?

4

8 回答 8

412
cut -d ' ' -f 2

其中 2 是您想要的以空格分隔的字段的字段编号。

于 2009-05-03T11:28:19.490 回答
214

通常,如果您使用空格作为分隔符,您希望将多个空格视为一个,因为您会解析将某些列与空格对齐的命令的输出。(和谷歌搜索带我到这里)

在这种情况下,单个cut命令是不够的,您需要使用:

tr -s ' ' | cut -d ' ' -f 2

或者

awk '{print $2}'
于 2013-09-28T16:59:24.447 回答
52

补充现有的有用答案;向QZ Support 致敬,鼓励我发布单独的答案:

两种不同的机制在这里发挥作用:

  • (a)cut 本身-d是否需要将传递给选项的分隔符(在这种情况下为空格)作为单独的参数,或者是否可以将其直接附加到-d.

  • (b) 在将参数传递给被调用的命令之前, shell通常如何解析参数。

(a) 引用了POSIX 公用事业指南(强调我的)

如果标准实用程序的 SYNOPSIS 显示带有强制选项参数的选项 [...],则符合要求的应用程序应为该选项及其选项参数使用单独的参数。但是,符合要求的实现还应允许应用程序在同一参数字符串中指定选项和选项参数,而无需插入字符

换句话说:在这种情况下,因为-d的 option-argument 是强制的,您可以选择是否将分隔符指定为

  • (s) EITHER: 一个单独的论点
  • (d) OR:作为直接附加-d的值。

一旦你选择了 (s) 或 (d),重要的是shell的字符串文字解析 - (b) -

  • 使用方法(s),以下所有形式都是等效的:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • 使用方法(d),以下所有形式都是等效的:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

等效性由shell的字符串文字处理解释:

上述所有解决方案在看到它们时都会产生完全相同的字符串(在每个组中)cut

  • (s) :cut-d, 作为它自己的参数,后跟一个包含空格字符的单独\参数 - 不带引号或前缀!。

  • (d) : cutsees-d 一个空格字符 - 不带引号或\前缀!- 作为同一论点的一部分。

基于shell解析字符串文字的方式,各个组中的形式最终相同的原因是双重的

  • shell 允许通过一种称为quoting的机制按原样指定文字,它可以采用多种形式
    • 单引号字符串:里面的内容按'...'字面意思理解并形成一个参数
    • 双引号字符串:里面的内容"..."也形成一个单一的参数,但受插值的影响(扩展变量引用,例如$var,命令替换($(...)`...`),或算术扩展($(( ... )))。
    • \-单个字符的引用:单个字符\前面的字符会导致该字符被解释为文字。
  • 引用由引号删除来补充,这意味着一旦 shell 解析了命令行,它就会从参数(封闭或或实例)中删除引号字符 - 因此,被调用的命令永远不会看到引号字符'...'"..."\
于 2015-05-02T03:52:49.097 回答
45

你也可以说:

cut -d\  -f 2

请注意,反斜杠后面有两个空格。

于 2009-05-03T20:47:35.993 回答
7

刚刚发现你也可以使用"-d "

cut "-d "

测试

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
于 2015-04-22T13:03:08.837 回答
5

如果数据有多个空格,你不能用 cut 轻松做到这一点。我发现标准化输入以便于处理很有用。一个技巧是使用 sed 进行标准化,如下所示。

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
于 2015-05-14T11:38:21.110 回答
3

scut,一个类似于 cut 的实用程序(我做的更聪明但更慢),可以使用任何 perl 正则表达式作为中断标记。在空白处打断是默认设置,但您也可以在多字符正则表达式、替代正则表达式等上打断。

scut -f='6 2 8 7' < input.file  > output.file

所以上面的命令将打破空白列并按该顺序提取(基于0的)cols 6 2 8 7。

于 2013-08-01T16:12:16.950 回答
0

我有一个答案(我承认有些令人困惑的答案)涉及sed、正则表达式和捕获组:

  • \S*- 第一个字
  • \s*- 分隔符
  • (\S*)- 第二个词 - 捕获
  • .*- 线路的其余部分

作为sed表达式,需要对捕获组进行转义,即\(and \)

返回捕获组的\1副本,即第二个单词。

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

当您查看此答案时,它有些令人困惑,并且您可能会想,为什么要打扰?好吧,我希望有些人可能会“啊哈!” 并将使用此模式通过单个sed表达式解决一些复杂的文本提取问题。

于 2018-05-29T06:11:06.640 回答