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

9udxz4iz  于 2023-08-04  发布在  Unix
关注(0)|答案(6)|浏览(133)

我试图从基于列的、“空间”调整的文本流中提取特定的(第四个)字段。我尝试以以下方式使用cut命令:
cat text.txt | cut -d " " -f 4
不幸的是,cut不将多个空格视为一个分隔符。我本可以通过awk
awk '{ printf $4; }'
或sed
sed -E "s/[[:space:]]+/ /g"
折叠空格,但我想知道是否有任何方法来处理cut和几个分隔符本机?

uubf1zoe

uubf1zoe1#

试试看:

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

字符串
来自tr手册页:

-s, --squeeze-repeats   replace each input sequence of a repeated character
                        that is listed in SET1 with a single occurrence
                        of that character

rryofs0p

rryofs0p2#

正如你在问题中所评论的那样,awk确实是一条路要走。使用cuttr -s可以压缩空间,如kev's answer所示。
不过,让我为未来的读者介绍一下所有可能的组合。说明见测试章节。

tr|切割

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

字符串

awk

awk '{print $4}' file

bash

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

bash

这将顺序读取字段。通过使用_,我们指出这是一个一次性变量,作为一个忽略这些字段的“垃圾变量”。这样,我们将$myfield存储为文件中的第4个字段,无论它们之间的空格是多少。

$ 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

vohkndzv

vohkndzv3#

最短/最友好的解决方案

在对cut的太多限制感到沮丧之后,我编写了自己的替代品,我称之为cuts,意思是“类固醇上的削减”。
cuts提供了可能是最简单的解决方案,以解决这个问题和 * 许多其他 * 相关的剪切/粘贴问题。
在众多例子中,有一个是针对这个问题的:

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

$ cuts 2 text.txt
2
2

字符串
cuts支持:

  • 自动检测文件中最常见的字段分隔符(+覆盖默认值的能力)
  • multi-char、mixed-char和regex匹配分隔符
  • 使用混合分隔符从多个文件中提取列
  • 除行开始外,距行结束的偏移量(使用负数)
  • 自动并排粘贴列(无需单独调用paste
  • 支持字段重新排序
  • 用户可以在其中更改其个人偏好的配置文件
  • 非常强调用户友好性和极简要求的打字

还有更多这些都不是标准cut提供的。
标签:https://stackoverflow.com/a/24543231/1296044
源代码和文档(自由软件):***http://arielf.github.io/cuts/***

0x6upsns

0x6upsns4#

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

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

字符串
但是,@F autossplit数组以索引$F[0]开始,而awk字段以$1开始

enyaitl3

enyaitl35#

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

41ik7eoe

41ik7eoe6#

我创建了a patch,它为cut添加了新的-m命令行选项,它在字段模式下工作,并将多个连续的分隔符视为单个分隔符。这基本上以一种相当有效的方式解决了OP的问题。几天前我还向上游提交了这个补丁,希望它能被合并到coreutils项目中。
有一些关于在cut中添加更多与空白相关的特性的further thoughts,并对所有这些都有一些反馈会很好。我愿意为cut实现更多的补丁并将它们提交到上游,这将使这个实用程序在各种现实场景中更加通用和可用。

相关问题