使用sed在分隔文件中内联交换X和X + 1列

时间:2014-04-09 22:30:30

标签: sed

我有一个包含多行的文件,而第2行到文件的末尾我想要交换字段8和9.文件以逗号分隔,我想进行内联交换,这样我就可以运行了使用*通配符的一批文件。如果这可以与awk类似地完成,那么这也适用于我。

示例:

header1,header2,header3,...,header8,header9,...,headerN
field1.1,...,field1.9,field1.8,...,field1.N
field2.1,...,field2.9,field2.8,...,field2.N
field3.1,...,field3.9,field3.8,...,field3.N
...

我认为该命令看起来与sed -r -i '2,$s/^(([^,]*,){8})([^,]*,)([^,]*,)(.*)/\1\3\2\4/' temp*.log类似 但是\2不是我所期望的,它是第7个领域。我知道\2不会是第8个字段,因为我有双括号,但我不知道如何解决它。有人可以解释这个等式正在做什么,特别是[^,]正在做什么以及如何应用{8}

提前致谢。

4 个答案:

答案 0 :(得分:2)

awk中,您可以使用:

awk -F',' 'BEGIN {OFS=","} {t = $8; $8 = $9; $9 = t; print}'

sed中,命令更复杂,但可以完成。

sed -e 's/^\(\([^,]*,\)\{7\}\)\([^,]*,\)\([^,]*,\)/\1\4\3/'

如果您的-i .bak版本(例如GNU或BSD)支持,请添加sed选项。

这使用普遍可用的sed正则表达式(它甚至适用于sed的古老版本)。如果您使用“扩展正则表达式”,则可能会丢失大部分反斜杠:

sed -r -i 's/^(([^,]*,){7})([^,]*,)([^,]*,)/\1\4\3\5/'

注意嵌套的记住(捕获)模式。外部集合为\1,内部集合为\2,但重复7次,因此您将第七个字段设为\2。无论如何,这就是第八和第九列与\4\3切换的原因。 \5是其余列。

(我顺便指出,以足够正确的格式提供一些样本数据进行测试会很有帮助。为了能够测试代码,必须编辑问题中显示的内容是令人讨厌的。)

如果您需要做很多CSV工作,请使用Perl及其CSV模块(Text::CSVText::CSV_XS)或Python及其CSV模块,或者获取CSVfix

答案 1 :(得分:1)

$ 2是RE

的第二部分

首次出现(会导致数据失效。

所以在

'2,$s/^(([^,]*,){8})([^,]*,)([^,]*,)(.*)/\1\3\2\4/'

你可以看到(followind alignment):

 $1 =  (([^,]*,){8})
 $2 =   ([^,]*,)
 $3 =               ([^,]*,)
 $4 =                       ([^,]*,)
 and finaly $5 =                    (.*)

在这种特定情况下,$2必须保持身高({8})的最后一次匹配

答案 2 :(得分:0)

似乎awk是正确的工具:

awk -F',' -v OFS=',' '{t=$8;$8=$9;$9=t}7' file

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed -ri '1!s/(,[^,]*)(,[^,]*)/\2\1/4' file

如果您想要第8个第8个,那么将第9个字段与第8个字段交换,即8/2 = 4:

sed -ri '1!{s/^/,/;s/(,[^,]*)(,[^,]*)/\2\1/4;s/^,//}' file