1

有没有一种简单的方法可以像这样交换表格文件中的列?

键将是第一列和第三列,但第二列应附加到第一列,第四列应附加到第三列。列之间的交换取决于第一个键(第 1 列)与第二个键(第 3 列)的存在。

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
4

2 回答 2

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函数会拆分$_on 空白的内容,并返回我们分配给 hash 的列表%h。重复键被删除;仅设置最后一次出现。

我们sortkeys字母顺序。map获取每个键并将键列表转换为交替键和值的列表,但这次的顺序正确。

我们join通过一个空格将这个字符串列表分配给$_,因为-p.

第二种解决方案:

-a选项自动进入数组split。我们取with的前两个元素,将它们放入一个匿名的 arrayref,并将这个 arrayref 推入array。我们重复直到没有元素剩下。这将 的内容配对,并且不受重复项的困扰。$_@F@Fsplice@f@F

我们按字母顺序sort将数组引用@f按其第一个元素放入,并用map. 之后,我们像以前一样加入字符串。

于 2013-02-05T21:26:46.163 回答
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
于 2013-02-05T20:45:18.110 回答