如何使“ cut”命令将顺序分隔符视为相同?


307

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

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

不幸的是,cut没有将多个空格视为一个定界符。我本来可以通过awk

awk '{ printf $4; }'

或sed

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

折叠空间,但是我想知道是否有任何方法可以处理,cut并且本机有几个定界符?


12
AWK是必经之路。
暂停,直到另行通知。

Answers:


545

尝试:

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

来自 tr手册页:

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

24
不需要cat这里。您可以< text.txt直接传递给tren.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat
arielf

1
不确定它是否更简单,但是您将要合并,可以放弃剪切-d并将直接从多个字符转换为制表符。例如:我到这里来是寻找一种自动导出我的显示的方法:who am i | tr -s ' ()' '\t' | cut -f5
Leo

与awk解决方案相比,这不会删除前导/尾随空格(可能不需要也可能不想要,但通常不是)。awk解决方案也更具可读性和冗长性。
n.caillou

-1 警告:这与处理顺序描述符不是一回事。比较echo "a b c" | cut -d " " -f2-echo "a b c" | tr -s " " | cut -d " " -f2-
user541686

96

在您对问题进行评论时,awk确实是要走的路。要使用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}。然后,它捕获到到第四个字段为止的所有内容,最后用来打印\1

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

2
awk它不仅优雅,简单,而且还包含在tr缺少的VMware ESXi中。
user121391

2
@ user121391还有另一个使用理由awk
fedorqui'SO停止伤害

@fedorqui我从未听说过下划线是“垃圾变量”。您可以对此提供更多的见解/参考吗?
BryKKan

1
@BryKKan是我在Greg的文章中了解到的。我如何逐行(和/或逐字段)读取文件(数据流,变量)?有些人使用一次性变量_作为“垃圾变量”来忽略字段。read如果我们不在乎它包含什么内容,也可以在单个命令中多次使用它(或者实际上是任何变量)。可以是任何东西,仅仅是它以某种方式代替了junk_var或成为了标准whatever:)
fedorqui'所以不要伤害

25

最短/最友好的解决方案

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

cuts为解决此问题以及许多其他相关的cut / paste问题提供了最简约的解决方案。

一个例子,解决了这个特定问题:

$ 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)并且具有固定数量的字段的文件。连续的两个分隔符表示一个空字段,也用于空格。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.