是否有一种简单的方法可以在列表文件中交换列?
键是第一列和第三列,但第二列应附加到第一列,第四列应附加到第三列。 列之间的交换取决于第一个键(第一个列)与第二个键(第三列)的存在。
A B C D
E F A B
H I A G
J K L M
N J Q K
所需的输出如下:
A B C D
A B E F
A G H I
J K L M
N J Q K
答案 0 :(得分:1)
这适合你:我可以用“单行”制作,但我认为以这种方式粘贴更容易阅读。
awk 'NR==1{a[$1];print;next;}!($1 in a){
r="";h=$1;
for(i=2;i<=NF;i++)
if($i in a){
for(m=i;m<=NF;m++)
r=(r?r" ":"")$m
break;
}else{
h=h" "$i
}
$0=(r?r" ":"")h;
}1' file
使用您的数据进行测试:
kent$ echo "A B C D
E F A B
H I A G
J K L M
N J Q K"|awk 'NR==1{a[$1];print;next;}!($1 in a){
r="";h=$1;
for(i=2;i<=NF;i++)
if($i in a){
for(m=i;m<=NF;m++)
r=(r?r" ":"")$m
break;
}else{
h=h" "$i
}
$0=(r?r" ":"")h;
}1'
A B C D
A B E F
A G H I
J K L M
N J Q K
答案 1 :(得分:1)
这是使用Perl的更简单的解决方案。如果同一行上的两个奇数列具有相同的内容,则会失败,例如
C D C A # Would print out "C A" only
否则,我们可以使用哈希数据结构来轻松操作键值对。
perl -ple'%h=split;$_=join" ",map{$_=>$h{$_}}sort keys %h'
示例用法:
$ perl -ple'%h=split;$_=join" ",map{$_=>$h{$_}}sort keys %h' <<'END'
A B C D
E F A B
H I A G
J K L M
N J Q K
END
输出:
A B C D
A B E F
A G H I
J K L M
N J Q K
没有那个弱点,我会像
那样写perl -pale'@f=();push@f,[splice@F,0,2]while@F;$_=join" ",map@$_,sort{$a->[0]cmp$b->[0]}@f'
基本上是Schwartzian变换。
选项-l
为我们处理行结尾。 -p
遍历所有输入行(将它们放在$_
中)并在每次迭代后打印出$_
的内容。
哈希被构造为交替键和值的列表。没有选项的split
函数在空格上拆分$_
的内容,并返回我们分配给散列%h
的列表。删除重复的密钥;只设置了最后一次出现。
我们sort
按字母顺序排列keys
。 map
获取每个键并将键列表转换为交替键和值的列表,但这次按正确顺序。
我们通过单个空格join
这个字符串列表并将其分配给$_
,由于-p
而打印出来。
-a
选项自动split
$_
进入@F
数组。我们将@F
的前两个元素与splice
一起使用,将它们放入匿名arrayref中,并将此arrayref推送到@f
数组中。我们重复,直到没有留下任何一个。这会将@F
的内容配对,而不会受到重复项的影响。
我们sort
@f
中的arrayrefs按字母顺序排列第一个元素,并使用map
将结果顺序展平。之后,我们像以前一样加入字符串。