如何让“cut”命令将相同的连续分隔符视为一个?

问题描述 投票:0回答:6

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

cut
命令:

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

不幸的是,

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

awk '{ printf $4; }'

或 sed

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

折叠空格,但我想知道是否有任何方法可以原生处理

cut
和几个分隔符?

bash unix delimiter cut
6个回答
589
投票

尝试:

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

来自

tr
手册页:

-s, --squeeze-repeats 替换重复字符的每个输入序列
                        SET1 中列出的单次出现的
                        那个角色的

105
投票

当您在问题中评论时,

awk
确实是正确的选择。使用
cut
可以与
tr -s
一起使用来压缩空间,如 kev 的答案 所示。

让我为未来的读者介绍一下所有可能的组合。说明位于测试部分。

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}
的空格。然后,它捕获任何到来的内容,直到第四个字段出现空格为止,最后打印出
\1

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4

27
投票

最短/最友好的解决方案

在对

cut
的太多限制感到沮丧后,我编写了自己的替代品,我将其称为
cuts
,意为“减少类固醇”。

剪切提供了针对此问题和许多其他相关剪切/粘贴问题的最简单的解决方案。

解决这个特定问题的众多示例中的一个:

$ 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/


4
投票

这段 Perl 行话显示了 Perl 与 awk 的关系有多么密切:

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

但是,

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

开始

3
投票

使用

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


1
投票

我创建了一个补丁,将新的

-m
命令行选项添加到
cut(1)
,它在字段模式下工作,并将多个连续分隔符视为单个分隔符。这基本上以相当有效的方式解决了OP的问题。几天前我也在上游提交了这个补丁,希望它能被接受并合并到 coreutils 项目中。

还有一些关于向 cut(1) 添加更多与空白相关的功能的

进一步的想法
,并且从不同的人那里得到一些反馈会很棒。我愿意为
cut(1)
实现更多补丁并将其提交到上游,这将使该实用程序在各种现实场景中更加通用且更可用。

© www.soinside.com 2019 - 2024. All rights reserved.