2013-03-26 56 views
1

我有一个文档A其中包含n行。我也有ň整数所有这些都是独特的,< ñ的序列。我的目标是创建具有相同内容一个文档,但与重新排序线,根据给定的顺序。按给定顺序重新排序文件行

实施例:

Foo 
Bar 
Bat 

序列:2,0,1

输出():

Bat 
Foo 
Bar 

在此先感谢您的帮助

+1

它不应该是'酒吧,蝙蝠,Foo'还是我失去了一些东西? – Taoufix 2013-03-26 14:46:18

+1

@axiom其实我明白了这样的问题:'Foo应该去2号位置,'酒吧到0号位置,'蝙蝠到1号位置。我需要更多的咖啡:) – Taoufix 2013-03-26 15:07:35

回答

5

另一种解决方案:

您可以创建这样一个序列文件(假设序列逗号分隔):

echo $sequence | sed s/,/\\n/g > seq.txt 

然后,就这样做:

paste seq.txt A.txt | sort tmp2.txt | sed "s/^[0-9]*\s//" 

这里有一个bash函数。订单可以由任何东西分隔。

用法:schwartzianTransform "A.txt" 2 0 1

function schwartzianTransform { 
    local file="$1" 
    shift 
    local sequence="[email protected]" 
    echo -n "$sequence" | sed 's/[^[:digit:]][^[:digit:]]*/\ 
/g' | paste -d ' ' - "$file" | sort -n | sed 's/^[[:digit:]]* //' 
} 
+4

这是众所周知的,作为[Schwartzian变换](http://en.wikipedia.org/wiki/Schwartzian_transform)。 – chepner 2013-03-26 16:20:56

+1

这是最接近我想要的。谢谢。 – L3viathan 2013-03-26 19:32:03

1

的一种方式(不是一个有效率的,虽然对于大文件):

$ seq="2 0 1" 
$ for i in $seq 
> do 
> awk -v l="$i" 'NR==l+1' file 
> done 
Bat 
Foo 
Bar 

如果您的文件是一个大的,你可以用这一个:

$ seq='2,0,1' 
$ x=$(echo $seq | awk '{printf "%dp;", $0+1;print $0+1> "tn.txt"}' RS=,) 
$ sed -n "$x" file | awk 'NR==FNR{a[++i]=$0;next}{print a[$0]}' - tn.txt 

第二行准备一个sed命令打印指令,然后将其与sed命令的第三行中使用。这将仅打印序列中存在的行号,但不打印序列的顺序。 awk命令用于根据序列对sed结果进行排序。

+2

首先我会说,这个工程。但它会通过文件**,整个文件**'n'次,每次只打印一行。如果文件很大,这将是痛苦的。我建议OP在午休前开始这个命令。有改进的余地。 – Kent 2013-03-26 15:07:46

+0

@Kent我现在实际上使用了一个简短的Python脚本,因为我需要一个解决方案,我只是觉得应该有一个标准的UNIX工具,专为这项工作而设计。显然没有一个。 – L3viathan 2013-03-26 19:31:15

1

文件读入到一个数组,然后使用索引的力量:

echo "Enter the input file name" 
read ip 

index=0 

while read line ; do 
     NAME[$index]="$line" 
      index=$(($index+1)) 
      done < $ip 

echo "Enter the file having order" 
read od 

while read line ; do 
     echo "${NAME[$line]}"; 
      done < $od 

[[email protected] sh]$ cat test 
Foo 
Bar 
Bat 
[[email protected] sh]$ cat od 
2 
0 
1 
[[email protected] sh]$ ./order.sh 
Enter the input file name 
test 
Enter the file having order 
od 
Bat 
Foo 
Bar 
1

一个awk oneliner可以做的工作:

awk -vs="$s" '{d[NR-1]=$0}END{split(s,a,",");for(i=1;i<=length(a);i++)print d[a[i]]}' file 

$s是你的序列。

看看这个例子:

kent$ seq 10 >file #get a 10 lines file 

kent$ s=$(seq 0 9 |shuf|tr '\n' ','|sed 's/,$//') # get a random sequence by shuf 

kent$ echo $s  #check the sequence in var $s 
7,9,1,0,5,4,3,8,6,2 

kent$ awk -vs="$s" '{d[NR-1]=$0}END{split(s,a,",");for(i=1;i<=length(a);i++)print d[a[i]]}' file                   
8 
10 
2 
1 
6 
5 
4 
9 
7 
3