我试图从基于列的、“空间”调整的文本流中提取某个(第四个)字段。我试图以以下方式使用cut命令:
4 . Cat text.txt | cut -d " " -f
不幸的是,cut不会将几个空格视为一个分隔符。我可以通过awk传输
Awk '{printf $4;} '
或sed
sed -E "s/[:space:]]+/ /g"
来折叠空格,但我想知道是否有任何方法来处理切割和几个分隔符?
我试图从基于列的、“空间”调整的文本流中提取某个(第四个)字段。我试图以以下方式使用cut命令:
4 . Cat text.txt | cut -d " " -f
不幸的是,cut不会将几个空格视为一个分隔符。我可以通过awk传输
Awk '{printf $4;} '
或sed
sed -E "s/[:space:]]+/ /g"
来折叠空格,但我想知道是否有任何方法来处理切割和几个分隔符?
当前回答
正如你在你的问题中所评论的,awk是真正的方法。正如kev的答案所示,可以使用cut和tr -s一起来压缩空间。
不过,让我把所有可能的组合都介绍给以后的读者。解释在测试部分。
Tr | cut
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
$ 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}的空格。然后,它捕获任何到来的东西,直到第4个空格字段,最后用\1打印出来。
$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
其他回答
这条Perl单行代码显示了Perl与awk的密切关系:
perl -lane 'print $F[3]' text.txt
但是,@F autosplit数组从索引$F[0]开始,而awk字段以$1开始
在我所知道的剪辑版本中,不,这是不可能的。Cut主要用于解析分隔符不是空格的文件(例如/etc/passwd),并且具有固定数量的字段。一行中有两个分隔符意味着一个空字段,这也适用于空格。
Try:
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
正如你在你的问题中所评论的,awk是真正的方法。正如kev的答案所示,可以使用cut和tr -s一起来压缩空间。
不过,让我把所有可能的组合都介绍给以后的读者。解释在测试部分。
Tr | cut
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
$ 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}的空格。然后,它捕获任何到来的东西,直到第4个空格字段,最后用\1打印出来。
$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
最短/ friendliest答案
在对cut的太多限制感到沮丧之后,我写了自己的替代品,我称之为cuts,意思是“类固醇上的cut”。
Cuts为这个问题以及许多其他相关的剪切/粘贴问题提供了可能是最简单的解决方案。
在众多例子中,有一个例子解决了这个特殊的问题:
$ cat text.txt
0 1 2 3
0 1 2 3 4
$ cuts 2 text.txt
2
2
削减支持:
auto-detection of most common field-delimiters in files (+ ability to override defaults) multi-char, mixed-char, and regex matched delimiters extracting columns from multiple files with mixed delimiters offsets from end of line (using negative numbers) in addition to start of line automatic side-by-side pasting of columns (no need to invoke paste separately) support for field reordering a config file where users can change their personal preferences great emphasis on user friendliness & minimalist required typing
还有更多。这些都不是标准切割提供的。
参见:https://stackoverflow.com/a/24543231/1296044
源代码和文档(免费软件):http://arielf.github.io/cuts/