bash-3.2$ cat f
Column1 Column2
str1 1
str2 2
str3 3
bash-3.2$ od -a f
0000000 C o l u m n 1 sp sp sp sp C o l u m
0000020 n 2 nl s t r 1 sp sp sp sp sp sp sp 1 nl
0000040 s t r 2 sp sp sp sp sp sp sp 2 nl s t r
0000060 3 sp sp sp sp sp sp sp 3 nl
0000072
变形:
bash-3.2$ sed "s/\([^ ]*\)[ ]*\([^ ]*\)[ ]*/\2 \1/" f
Column2 Column1
1 str1
2 str2
3 str3
bash-3.2$ sed "s/\([^ ]*\)[ ]*\([^ ]*\)[ ]*/\2 \1/" f | od -a
0000000 C o l u m n 2 sp C o l u m n 1 nl
0000020 1 sp s t r 1 nl 2 sp s t r 2 nl 3 sp
0000040 s t r 3 nl
0000045
保留列宽
现在,让我们将该方法扩展到具有恒定宽度列的文件,同时允许列具有不同的宽度。 档案:
bash-3.2$ cat f2
Column1 Column2
str1 1
str2 2
str3 3
bash-3.2$ od -a f2
0000000 C o l u m n 1 sp sp sp sp C o l u m
0000020 n 2 nl s t r 1 sp sp sp sp sp sp sp 1 sp
0000040 sp sp sp sp sp nl s t r 2 sp sp sp sp sp sp
0000060 sp 2 sp sp sp sp sp sp nl s t r 3 sp sp sp
0000100 sp sp sp sp 3 sp sp sp sp sp sp nl
0000114
变形:
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f2
Column2 Column1
1 str1
2 str2
3 str3
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f2 | od -a
0000000 C o l u m n 2 sp C o l u m n 1 sp
0000020 sp sp nl 1 sp sp sp sp sp sp sp s t r 1 sp
0000040 sp sp sp sp sp nl 2 sp sp sp sp sp sp sp s t
0000060 r 2 sp sp sp sp sp sp nl 3 sp sp sp sp sp sp
0000100 sp s t r 3 sp sp sp sp sp sp nl
0000114
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f3
Column2 Column1
1 str1
2 string2
3 str3
bash-3.2$ sed "s/\([^ ]*\)\([ ]*\) \([^ ]*\)\([ ]*\)/\3\4 \1\2/" f3 | od -a
0000000 C o l u m n 2 sp C o l u m n 1 sp
0000020 sp sp nl 1 sp sp sp sp sp sp sp s t r 1 sp
0000040 sp sp sp sp sp nl 2 sp sp sp sp sp sp sp s t
0000060 r i n g 2 sp sp sp nl 3 sp sp sp sp sp sp
0000100 sp s t r 3 sp sp sp sp sp sp nl
0000114
这里, -e告诉Perl内联查找代码,而不是在单独的脚本文件中查找, -n一次读取输入的1行, -l在阅读行后删除输入记录分隔符(\n on *NIX)(类似于chomp),并将输出记录分隔符(\n on *NIX)添加到每个print、 -a将空白上的输入行拆分为数组@F, -F'\t'与-a结合使用时,会将TAB上的输入行(而不是空格)拆分到数组@F中。 @F[1, 0]是由数组@F中的第2个元素和第1个元素组成的数组。请记住,Perl中的数组是零索引的,而cut中的字段是1索引的。因此,@F[0, 1]中的字段与cut -f1,2中的字段是相同的。 请注意,与上面发布的其他一些答案相比,这样的表示法可以更灵活地处理输入(对于简单的任务来说很好)。例如:
# reverses the order of fields:
perl -F'\t' -lane 'print join "\t", reverse @F' in_file
# prints last and first fields only:
perl -F'\t' -lane 'print join "\t", @F[-1, 0]' in_file
9条答案
按热度按时间anhgbhbe1#
有关
cut(1)
手册页,请参阅:请使用-B、-c或-f中的一个,且只能使用其中一个。每个LIST由一个范围或多个范围组成,范围之间用逗号分隔。所选输入的写入顺序与读取顺序相同,并且只写入一次。
它首先到达字段1,以便打印,然后是字段2。
请改用
awk
:vom3gejh2#
您也可以将
cut
和paste
结合使用:通过评论:可以通过以下方式避免害羞并消除一个剪切示例:
c9x0cxw03#
使用
join
:备注:
-t $'\t'
在 GNUjoin
中,更直观的-t '\t'
* 没有 *$
失败,(coreutils**v8.28 和更早版本?);这可能是一个bug,需要使用$
之类的解决方法。请参见:unix join separator char。join
语法也需要 * 两个 * 文件名。重复文件名可以让join
执行所需的操作。join
比其他答案中使用的一些工具占用的空间更小:8ehkhllq4#
仅使用 shell ,
bnl4lu3b5#
您可以使用Perl来实现这一点:
运行Perl的好处是(如果您了解Perl),与重新排列列相比,您可以在F上执行更多的计算。
ds97pgxw6#
只是一直在做一些非常相似的事情,我不是Maven,但我想我会分享我用过的命令。我有一个多列csv,我只需要4列出来,然后我需要重新排序它们。
我的文件被管'|'分隔,但可以换出。
诚然,这是真的粗糙和准备,但它可以调整,以适应!
vu8f3i0k7#
正如对建议复制列然后执行
cut
的回答的补充。对于复制,paste
等将仅适用于文件,而不适用于流。在这种情况下,请改用sed
。cat file.txt | sed s/'.*'/'&\t&'/ | cut -f2,3
这对文件和流都有效,如果不是仅仅用
cat
阅读文件,而是在重新排列列之前做一些有趣的事情,这就很有趣了。相比之下,以下方法不起作用:
cat file.txt | paste - - | cut -f2,3
这里,双stdin占位符
paste
不复制stdin,但读取下一行。qzwqbdag8#
使用sed
使用
sed
和基本正则表达式的嵌套子表达式来捕获列内容并对其进行重新排序。这种方法最适合用于对列进行重新排序的剪切次数有限的情况,如本例所示。基本思想是用
\(
和\)
包围搜索模式的感兴趣部分,这些部分可以在用\#
的替换模式中回放,其中#
表示子表达式在搜索模式中的顺序位置。例如:
产量:
扫描子运算式之外的文字,但不会在取代字串中保留以供播放。
虽然这个问题没有讨论固定宽度的列,我们将在这里讨论,因为这是一个值得衡量的任何解决方案提出。为简单起见,让我们假设文件是空格分隔的,虽然解决方案可以扩展为其他分隔符。
折叠空格
为了说明最简单的用法,让我们假设多个空格可以折叠成单个空格,并且第二列的值以EOL结束(而不是填充空格)。
档案:
变形:
保留列宽
现在,让我们将该方法扩展到具有恒定宽度列的文件,同时允许列具有不同的宽度。
档案:
变形:
最后,虽然问题的示例没有不等长的字符串,但这个
sed
表达式支持这种情况。档案:
变形:
与Shell下其他列重排序方法的比较
awk
并不适合从一个字段剪切到记录的结尾。在sed
中,这可以使用正则表达式来完成,例如\(xxx.*$\)
,其中xxx
是匹配列的表达式。paste
和cut
子shell会很棘手。从命令行运行的代码在进入shell脚本时无法解析。至少这是我的经验(驱使我使用这种方法)。js5cn81o9#
扩展来自@Met的答案,同样使用Perl:
如果输入和输出以制表符分隔:
如果输入和输出以空格分隔:
这里,
-e
告诉Perl内联查找代码,而不是在单独的脚本文件中查找,-n
一次读取输入的1行,-l
在阅读行后删除输入记录分隔符(\n
on *NIX)(类似于chomp
),并将输出记录分隔符(\n
on *NIX)添加到每个print
、-a
将空白上的输入行拆分为数组@F
,-F'\t'
与-a
结合使用时,会将TAB上的输入行(而不是空格)拆分到数组@F
中。@F[1, 0]
是由数组@F
中的第2个元素和第1个元素组成的数组。请记住,Perl中的数组是零索引的,而cut
中的字段是1索引的。因此,@F[0, 1]
中的字段与cut -f1,2
中的字段是相同的。请注意,与上面发布的其他一些答案相比,这样的表示法可以更灵活地处理输入(对于简单的任务来说很好)。例如: