交换两列的内容

交换两列的内容

我试图更好地理解剪切并将剪切数据移动到另一个文件。我有一个名为“数字”的文件,有两列。每列由一个选项卡分隔。

我试图通过使用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都必须读取原始数据两次(通常,如果要反转所有列,则读取次数与列数一样多)。

相关内容