71

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

该文件是制表符分隔的:

Affy-id chr 0 pos NA06984 NA06985 NA06986 NA06989
4

9 回答 9

122

您可以通过交换前两个字段的值来做到这一点:

awk ' { t = $1; $1 = $2; $2 = t; print; } ' input_file
于 2012-08-15T10:35:48.040 回答
26

我在带有制表符分隔文件的 Windows 系统上用 cygwin 尝试了 perreal 的答案。它不起作用,因为标准分隔符是空格。

如果您遇到同样的问题,请尝试以下操作:

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
于 2015-04-09T07:37:19.830 回答
11

试试这个与您的问题更相关:

awk '{printf("%s\t%s\n", $2, $1)}' inputfile
于 2016-12-08T10:43:36.270 回答
5

这可能对您有用(GNU sed):

sed -i 's/^\([^\t]*\t\)\([^\t]*\t\)/\2\1/' file
于 2012-08-15T11:08:09.660 回答
3

您是否尝试过使用 cut 命令?例如

cat myhugefile | cut -c10-20,c1-9,c21- > myrearrangedhugefile
于 2012-08-15T10:42:35.227 回答
3

这在 perl 中也很容易:

perl -pe 's/^(\S+)\t(\S+)/$2\t$1/;' file > outputfile
于 2015-06-01T23:01:26.130 回答
2

你可以在 Perl 中做到这一点:

perl -F\\t -nlae 'print join("\t", @F[1,0,2..$#F])' inputfile

-F指定分隔符。在大多数 shell 中,您需要在反斜杠前面加上另一个来转义它。在某些平台上-F自动暗示-n-a因此它们可以被删除。

对于您的问题,您不需要使用-l,因为最后一列出现在输出的最后。但是如果在不同的情况下,如果最后一列需要出现在其他列之间,则必须删除换行符。-l交换机负责这一点。

可以将"\t"in 连接更改为其他任何内容,以在输出中生成不同的分隔符。

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

于 2015-07-02T06:15:47.643 回答
2

除了你的shell,不需要调用其他任何东西:

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
于 2020-02-05T14:25:59.577 回答
0

甚至可能使用“内联” Python - 就像在 shell 脚本中的 Python 脚本中一样 -前提是您想事先或之后使用 Bash 进行更多脚本编写......否则它会变得不必要地复杂。

脚本文件内容process.sh

#!/bin/bash

# inline Python script
read -r -d '' PYSCR << EOSCR
from __future__ import print_function
import codecs
import sys

encoding = "utf-8"
fn_in = sys.argv[1]
fn_out = sys.argv[2]

# print("Input:", fn_in)
# print("Output:", fn_out)

with codecs.open(fn_in, "r", encoding) as fp_in, \
        codecs.open(fn_out, "w", encoding) as fp_out:
    for line in fp_in:
        # split into two columns and rest
        col1, col2, rest = line.split("\t", 2)
        # swap columns in output
        fp_out.write("{}\t{}\t{}".format(col2, col1, rest))
EOSCR

# ---------------------
# do setup work?
# e. g. list files for processing

# call python script with params
python3 -c "$PYSCR" "$inputfile" "$outputfile"

# do some more processing
# e. g. rename outputfile to inputfile, ...

如果您只需要为单个文件交换列,那么您也可以只创建一个 Python 脚本并静态定义文件名。或者只是使用上面的答案。

于 2020-01-20T16:22:40.600 回答