交换两列—awk、sed、python和perl

交换两列—awk、sed、python和perl,sed,awk,Sed,Awk,我有一个大文件中的数据(280列宽,700万行长!),我需要交换前两列。我想我可以用某种awk for循环来实现这一点,打印$2、$1,然后在文件末尾打印一个范围-但是我不知道如何做范围部分,我不能打印$2、$1、$3…$280!我在这里看到的大多数列交换答案都是针对具有可管理列数的小文件的,因此我需要一些不依赖于指定每个列数的东西 该文件以制表符分隔: Affy-id chr 0 pos NA06984 NA06985 NA06986 NA06989 可以通过交换前两个字段的值来执行此操作:

我有一个大文件中的数据(280列宽,700万行长!),我需要交换前两列。我想我可以用某种awk for循环来实现这一点,打印$2、$1,然后在文件末尾打印一个范围-但是我不知道如何做范围部分,我不能打印$2、$1、$3…$280!我在这里看到的大多数列交换答案都是针对具有可管理列数的小文件的,因此我需要一些不依赖于指定每个列数的东西

该文件以制表符分隔:

Affy-id chr 0 pos NA06984 NA06985 NA06986 NA06989

可以通过交换前两个字段的值来执行此操作:

awk ' { t = $1; $1 = $2; $2 = t; print; } ' input_file

您是否尝试过使用“剪切”命令?例如

cat myhugefile | cut -c10-20,c1-9,c21- > myrearrangedhugefile
这可能适用于您(GNU-sed):


我尝试了perreal和cygwin在windows系统上使用选项卡分隔文件的答案。它不起作用,因为标准分隔符是空格

如果遇到相同的问题,请尝试以下方法:

awk -F $'\t' ' { t = $1; $1 = $2; $2 = t; print; } ' OFS=$'\t' input_file
传入分隔符由
-F$'\t'
定义,输出分隔符由
OFS=$'\t'
定义

awk -F $'\t' ' { t = $1; $1 = $2; $2 = t; print; } ' OFS=$'\t' input_file > output_file

这在perl中也很容易:

perl -pe 's/^(\S+)\t(\S+)/$2\t$1/;' file > outputfile

您可以在Perl中执行此操作:

perl -F\\t -nlae 'print join("\t", @F[1,0,2..$#F])' inputfile
-F
指定分隔符。在大多数shell中,您需要在反斜杠之前加上另一个反斜杠以避开它。在某些平台上,
-F
自动表示
-n
-a
,因此可以删除它们

对于您的问题,您不需要使用
-l
,因为最后一列显示在输出中的最后一列。但是,如果在不同的情况下,如果最后一列需要出现在其他列之间,则必须删除换行符。
-l
开关负责此操作

join中的
“\t”
可以更改为任何其他内容,以在输出中生成不同的分隔符


2..$#F
指定从2到最后一列的范围。正如您可能猜到的,在方括号内,您可以按所需顺序放置任意一列或一系列列。

尝试与您的问题更相关的方法:

awk '{printf("%s\t%s\n", $2, $1)}' inputfile
甚至可以使用“内联”Python(如shell脚本中的Python脚本),但只有在您想在之前或之后使用Bash进行更多脚本编写时才可以。。。否则它就不必要地复杂了

脚本文件的内容
process.sh

#/bin/bash
#内联Python脚本

read-r-d''PYSCR除了您的shell之外,无需调用其他任何东西:

bash> while read col1 col2 rest; do 
        echo $col2 $col1 $rest
      done <input_file

那是如此的整洁和优雅,谢谢你!我希望会有一个单一的班轮在那里。这个答案是有问题的不同大小的列和他们的分离器。这里使用
-F'\t'
选项卡的更具扩展性的答案在最终输出中被消耗掉。有办法保存它们吗?好的,必须指定
OFS=$'\t'
,如下所示@perreal,也许用附加参数更新答案是值得的?如果您使用:
awk'{print$2,$1}'
是一样的:DI没有,但我会记住这一点,以备将来使用-c=字符。。。因此,这不会交换列。它将交换输出文件中的列-请自己尝试。我们如何在不知道字符数的情况下进行交换
cat myhugefile | cut-f2,1
提供与
cat myhugefile | cut-f1,2
相同的输出。您可以将每列输出到中间文件。类似于:cut-f2 myhugefile>piece1;剪切-f1 myhugefile>piece2 |粘贴piece1 piece2>myhugefile;rm-1;rm piece2Super!我缺少OFS=$'\t'
参数!这种方法最终可能会在行的开头出现制表符。可能不是预期的结果。这仅打印前两列。更简洁的是
awk'{print$2”\t“$1}”输入文件
bash> while read col1 col2 rest; do 
        echo $col2 $col1 $rest
      done <input_file
bash> echo "first second a c d e f g" | 
      while read col1 col2 rest; do 
        echo $col2 $col1 $rest
      done
second first a b c d e f g