交换两列-awk、 sed、 python、 perl

我在一个大文件中获得了数据(280列宽,700万行长!)我需要交换前两栏。我想我可以使用 awk for 循环,打印 $2,$1,然后打印一个到文件末尾的范围-但我不知道如何打印范围部分,我不能打印 $2,$1,$3... $280!我在这里看到的大多数列交换答案都是特定于具有可管理的列数的小文件的,所以我需要一些不依赖于指定每个列号的内容。

该文件以制表符分隔:

Affy-id chr 0 pos NA06984 NA06985 NA06986 NA06989
83772 次浏览

可以通过交换前两个字段的值来实现:

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

你试过使用 cut 命令吗。

cat myhugefile | cut -c10-20,c1-9,c21- > myrearrangedhugefile

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

sed -i 's/^\([^\t]*\t\)\([^\t]*\t\)/\2\1/' file

我在 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

这在 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开关可以解决这个问题。

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

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

试试这个更适合你的问题:

awk '{printf("%s\t%s\n", $2, $1)}' inputfile

也许甚至在使用 “内嵌” Python 时——就像在 Python 脚本中使用 shell 脚本一样——只有在您希望事先或事后使用 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 脚本并静态定义文件名。或者直接用上面的答案。

除了你的外壳,没必要叫别的:

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

交换 < strong > sans temp-variable :

echo '777777744444444464449: 317 647 14423 262927714037  :   0x2A29D5A1BAA7A95541' |
mawk '1; ($1 = $2 substr(_, ($2 = $1)^_))^_' FS=':' OFS=':'
777777744444444464449: 317 647 14423 262927714037  :   0x2A29D5A1BAA7A95541


317 647 14423 262927714037  :777777744444444464449:   0x2A29D5A1BAA7A95541