326

我正在尝试从基于列的“空格”调整文本流中提取某个(第四个)字段。我正在尝试以cut下列方式使用该命令:

cat text.txt | cut -d " " -f 4

不幸的是,cut不会将多个空格视为一个分隔符。我本可以通过 awk 进行管道传输

awk '{ printf $4; }'

或 sed

sed -E "s/[[:space:]]+/ /g"

折叠空格,但我想知道是否有任何方法可以处理cut本地的几个分隔符?

4

5 回答 5

575

尝试:

tr -s ' ' <text.txt | cut -d ' ' -f4

tr手册页:

-s, --squeeze-repeats 替换每个重复字符的输入序列
                        在 SET1 中仅出现一次
                        那个性格的
于 2010-12-19T16:22:01.003 回答
100

正如您在问题中评论的那样,awk这确实是要走的路。正如kev的回答所示,可以与压缩空间cut一起使用。tr -s

然而,让我为未来的读者介绍所有可能的组合。说明在测试部分。

tr | 切

tr -s ' ' < file | cut -d' ' -f4

awk

awk '{print $4}' file

重击

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

测试

给定这个文件,让我们测试一下命令:

$ cat a
this   is    line     1 more text
this      is line    2     more text
this    is line 3     more text
this is   line 4            more    text

tr | 切

$ cut -d' ' -f4 a
is
                        # it does not show what we want!


$ tr -s ' ' < a | cut -d' ' -f4
1
2                       # this makes it!
3
4
$

awk

$ awk '{print $4}' a
1
2
3
4

重击

这会按顺序读取字段。通过使用_我们表明这是一个一次性变量作为“垃圾变量”来忽略这些字段。这样,$myfield无论它们之间的空格如何,我们都将其存储为文件中的第四个字段。

$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4

sed

这会捕获三组空格,并且没有空格([^ ]*[ ]*){3}。然后,它会捕获任何出现的内容,直到作为第 4 个字段的空格,最终打印为\1.

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
于 2014-09-23T10:27:46.190 回答
27

最短/最友好的解决方案

在对 的太多限制感到沮丧之后cut,我编写了自己的替代品,我呼吁cuts“减少类固醇”。

cut为这个问题和许多其他相关的剪切/粘贴问题提供了最简单的解决方案。

在众多例子中,有一个例子解决了这个特定的问题:

$ cat text.txt
0   1        2 3
0 1          2   3 4

$ cuts 2 text.txt
2
2

cuts支持:

  • 自动检测文件中最常见的字段分隔符(+ 覆盖默认值的能力)
  • 多字符、混合字符和正则表达式匹配的分隔符
  • 从具有混合分隔符的多个文件中提取列
  • 除了行首之外,从行尾偏移(使用负数)
  • 自动并排粘贴列(无需paste单独调用)
  • 支持字段重新排序
  • 一个配置文件,用户可以在其中更改他们的个人偏好
  • 非常强调用户友好性和极简所需的打字

以及更多。这些都不是由标准提供的cut

另请参阅:https ://stackoverflow.com/a/24543231/1296044

源代码和文档(免费软件):http ://arielf.github.io/cuts/

于 2014-07-03T01:04:29.147 回答
4

这个 Perl 单行代码显示了 Perl 与 awk 的关系有多密切:

perl -lane 'print $F[3]' text.txt

但是,@F自动拆分数组从索引开始,$F[0]而 awk 字段以$1

于 2015-09-09T17:16:04.660 回答
3

使用cut我所知道的版本,不,这是不可能的。cut主要用于解析分隔符不是空格(例如/etc/passwd)且具有固定数量的字段的文件。连续的两个分隔符表示一个空字段,这也适用于空格。

于 2010-11-10T10:37:21.843 回答