我有一个包含多行的文件,而第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}
?
提前致谢。
答案 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::CSV和Text::CSV_XS)或Python及其CSV模块,或者获取CSVfix。
答案 1 :(得分:1)
首次出现(
会导致数据失效。
所以在
'2,$s/^(([^,]*,){8})([^,]*,)([^,]*,)(.*)/\1\3\2\4/'
你可以看到(followind alignment):
$1 = (([^,]*,){8})
$2 = ([^,]*,)
$3 = ([^,]*,)
$4 = ([^,]*,)
and finaly $5 = (.*)
在这种特定情况下,$2
必须保持身高({8}
)的最后一次匹配。
答案 2 :(得分:0)
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