我正在尝试从基于列的“空格”调整文本流中提取某个(第四个)字段。我正在尝试以cut
下列方式使用该命令:
cat text.txt | cut -d " " -f 4
不幸的是,cut
不会将多个空格视为一个分隔符。我本可以通过 awk 进行管道传输
awk '{ printf $4; }'
或 sed
sed -E "s/[[:space:]]+/ /g"
折叠空格,但我想知道是否有任何方法可以处理cut
本地的几个分隔符?
尝试:
tr -s ' ' <text.txt | cut -d ' ' -f4
从tr
手册页:
-s, --squeeze-repeats 替换每个重复字符的输入序列 在 SET1 中仅出现一次 那个性格的
正如您在问题中评论的那样,awk
这确实是要走的路。正如kev的回答所示,可以与压缩空间cut
一起使用。tr -s
然而,让我为未来的读者介绍所有可能的组合。说明在测试部分。
tr -s ' ' < file | cut -d' ' -f4
awk '{print $4}' file
while read -r _ _ _ myfield _
do
echo "forth field: $myfield"
done < file
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
$ 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 '{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
这会捕获三组空格,并且没有空格([^ ]*[ ]*){3}
。然后,它会捕获任何出现的内容,直到作为第 4 个字段的空格,最终打印为\1
.
$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
在对 的太多限制感到沮丧之后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/
这个 Perl 单行代码显示了 Perl 与 awk 的关系有多密切:
perl -lane 'print $F[3]' text.txt
但是,@F
自动拆分数组从索引开始,$F[0]
而 awk 字段以$1
使用cut
我所知道的版本,不,这是不可能的。cut
主要用于解析分隔符不是空格(例如/etc/passwd
)且具有固定数量的字段的文件。连续的两个分隔符表示一个空字段,这也适用于空格。