如何使“剪切”命令将相同的连续分隔符视为一个?
Posted
技术标签:
【中文标题】如何使“剪切”命令将相同的连续分隔符视为一个?【英文标题】:How to make the 'cut' command treat same sequental delimiters as one? 【发布时间】:2011-05-07 19:03:13 【问题描述】:我正在尝试从基于列的“空格”调整文本流中提取某个(第四个)字段。我正在尝试以下列方式使用cut
命令:
cat text.txt | cut -d " " -f 4
很遗憾,cut
不会将多个空格视为一个分隔符。我可以通过 awk 进行管道传输
awk ' printf $4; '
或sed
sed -E "s/[[:space:]]+/ /g"
折叠空格,但我想知道是否有任何方法可以原生处理cut
和几个分隔符?
【问题讨论】:
AWK 是要走的路。 linux cut help - how to specify more spaces for the delimiter?的可能重复 【参考方案1】:对于cut
的版本,我知道,不,这是不可能的。 cut
主要用于解析分隔符不是空格的文件(例如/etc/passwd
)并且具有固定数量的字段。一行中的两个分隔符表示一个空字段,空格也一样。
【讨论】:
【参考方案2】:试试:
tr -s ' ' <text.txt | cut -d ' ' -f4
来自tr
手册页:
【讨论】:
这里不需要cat
。您可以将< text.txt
直接传递给tr
。 en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat
不确定它是否更简单,但您要合并,您可以放弃剪切的-d
并直接从多个字符转换为制表符。例如:我来这里是为了寻找一种自动导出我的显示的方法:who am i | tr -s ' ()' '\t' | cut -f5
与 awk 解决方案相比,这不会删除前导/尾随空格(可能需要也可能不需要,但通常不需要)。 awk 解决方案也更具可读性和更少冗长。
-1 警告:这与将连续分隔符视为一个不同。 比较echo "a b c" | cut -d " " -f2-
、echo "a b c" | tr -s " " | cut -d " " -f2-
【参考方案3】:
最短/最友好的解决方案
在对 cut
的太多限制感到沮丧之后,我编写了自己的替代品,我称其为 cuts
以表示“减少类固醇”。
众多例子中的一个,解决了这个特定的问题:
$ cat text.txt
0 1 2 3
0 1 2 3 4
$ cuts 2 text.txt
2
2
cuts
支持:
paste
)
支持字段重新排序
用户可以在其中更改个人偏好的配置文件
非常重视用户友好性和极简要求的输入
等等。这些都不是标准cut
提供的。
另请参阅:https://***.com/a/24543231/1296044
源和文档(免费软件):http://arielf.github.io/cuts/
【讨论】:
【参考方案4】:正如您在问题中评论的那样,awk
确实是要走的路。 cut
可以与tr -s
一起使用来压缩空间,如kev's answer 所示。
让我为未来的读者介绍所有可能的组合。说明在测试部分。
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
存储为文件中的第 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
没有空格。然后,它会捕获任何出现的内容,直到作为第 4 个字段的空格,最终打印为 \1
。
$ sed -r 's/^([^ ]*[ ]*)3([^ ]*).*/\2/' a
1
2
3
4
【讨论】:
awk
不仅优雅简洁,而且还包含在 VMware ESXi 中,其中缺少 tr
。
@user121391 又一个使用awk
的理由!
@fedorqui 我从来没有听说过下划线是“垃圾变量”。您能否就此提供更多见解/参考?
@BryKKan 我在 Greg 的How can I read a file (data stream, variable) line-by-line (and/or field-by-field)? 中了解到它:有些人使用一次性变量 _ 作为“垃圾变量”来忽略字段。如果我们不关心其中的内容,它(或实际上任何变量)也可以在单个read
命令中多次使用。它可以是任何东西,只是它以某种方式成为标准而不是 junk_var
或 whatever
:)
@BryKKan 在 javascript 中它也代表一个不打算使用的函数参数。【参考方案5】:
这个 Perl 单行显示 Perl 与 awk 的关系有多密切:
perl -lane 'print $F[3]' text.txt
但是,@F
自动拆分数组从索引 $F[0]
开始,而 awk 字段以 $1
开始
【讨论】:
以上是关于如何使“剪切”命令将相同的连续分隔符视为一个?的主要内容,如果未能解决你的问题,请参考以下文章