我试图更好地理解剪切并将剪切数据移动到另一个文件。我有一个名为“数字”的文件,有两列。每列由一个选项卡分隔。
我试图通过使用cut
命令交换列并将cut
命令输出保存到另一个文件。我可以毫无问题地剪切字段 2 并将输出保存到copynumber
文件中。但我不知道如何cut
在输出文件中将字段 1 字段转换为字段 2 。
我正在寻找仅使用 bash shell 脚本而不是任何其他语言(例如awk
.
#I have tried the following commands:
$cat numbers
1 2
10 20
100 200
1000 2000
10000 20000
100000 300000
1000000 3000000
cat numbers | cut -f 2 > copynumbers
#How do I get field 1 from the original file into field 2 of the output file?
$cat copynumbers
2
20
200
2000
20000
300000
3000000
答案1
如果您熟悉 Perl,此类实用程序的集合之一可能会很有用。这里 TSV 输入位于文件 z5 上:
$ recut 2,1 z5
2 1
20 10
200 100
2000 1000
20000 10000
300000 100000
3000000 1000000
关于重新切入的一些信息缺失的 Textutils收藏:
recut Process fields like cut, allow repetitions and re-ordering. (what)
Path : ~/bin/recut
Version : - ( local: RepRev 1.1, ~/bin/recut, 2010-06-10 )
Length : 56 lines
Type : Perl script, ASCII text executable
Shebang : #!/usr/bin/perl
Home : http://www1.cuni.cz/~obo/textutils/ (doc)
Modules : (for perl codes)
Getopt::Long 2.42
我们店通用的tac来处理这样的情况:
$ my-tac --field=0 z5
2 1
20 10
200 100
2000 1000
20000 10000
300000 100000
3000000 1000000
到目前为止,我们还没有发布我们的库,但如果您想重新创建它,这是帮助:
my-tac - reverse any one property: lines (like tac), fields, characters.
The default is to reverse the lines in a file, so a file like:
a
b
c
will be printed as:
c
b
a
usage: my-tac [options] -- [files]
options:
--help (or -h)
print this message and quit.
--character
Reverse order of characters in each line. That is, given:
abc
the result is:
cba
--field=0
Reverse order of fields. That is, given:
Now is the time
the result is:
time the is Now
--field=i,j,k
Reverse content of specific fields i,j,k. That is given
Now is the time
my-tac --field=1,3 wil result in:
woN is eht time
--para
Reverse order of paragraphs, which are groups of lines
separated by one of more empty lines. If the last paragraph is
not followed by an enpty line, one is supplied.
--number=n
Print only n lines for a file reversal. <no limit>.
--debug
Print internal debugging information. <off>.
(Must be first option.)
--separator=",re,string"
Set the input separator to regular expression re, <\s+>, and
the output separator to string, < >. So the default is
",\s+, ". Any character may be used in place of the comma, so
you could specify:
--separator=';\s+;|'
最美好的祝愿...干杯,drl
答案2
使用流程替代和paste
:
$ paste <(cut -f2 numbers) <(cut -f1 numbers)
2 1
20 10
200 100
2000 1000
20000 10000
300000 100000
3000000 1000000
答案3
我认为,用于awk
解决此任务的方法属于通常被认为是“shell 脚本”的范畴:
awk -F '\t' 'BEGIN { OFS=FS } { print $2, $1 }'
首先使用 将输入分隔符设置为制表符-F '\t'
,然后该BEGIN
块将输出分隔符设置为相同的字符。 only 块的主体只是以相反的顺序输出两个字段。
测试:
$ awk -F '\t' 'BEGIN { OFS=FS } { print $2, $1 }' numbers
2 1
20 10
200 100
2000 1000
20000 10000
300000 100000
3000000 1000000
反转所有列(无论有多少列)的更通用方法:
BEGIN { OFS=FS }
{
for (i = 1; i <= NF/2; ++i ) {
t=$i; $i=$(NF-i+1); $(NF-i+1)=t
}
print
}
这将从行的开头到中间遍历各列,将每个列与末尾的相应列交换。对于具有奇数列的输入数据,中间列将保持不变。
使用使用其中一列创建临时文件的初始方法也可以:
cut -f 2 numbers >tmpfile
将原始文件粘贴到此文件将创建一个包含三列的数据集(再次是第 2、1 和 2 列):
paste tmpfile numbers
然后我们可以使用以下命令删除最后一列cut
:
paste tmpfile numbers | cut -f 1,2
或者,我们可以不使用该临时文件来启动:
cut -f 2 numbers | paste - numbers | cut -f 1,2
请注意,使用的所有解决方案cut
都必须读取原始数据两次(通常,如果要反转所有列,则读取次数与列数一样多)。