使用 awk 重新排列列

使用 awk 重新排列列

我正在尝试使用以下方法将 csv 文件的第 7 列移动到末尾

awk -F '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}',OFS= "$file"

其中 $file 是目录中的 .csv 文件。然而,输出是

awk:                          ^ syntax error

有谁知道如何修复这个错误?

答案1

-F选项需要一个参数(字段分隔符):-F,例如。

脚本末尾必须与其余参数用(空格字符)awk分隔。

如果字段分隔符是,并且您希望保留它,并且列数恒定且小于或等于 11,请尝试以下操作:

awk -F, '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=, "$file"

如果您的字段分隔符是分号,请不要忘记将其设置在引号中,如下所示

awk -f';' '{print $1,$2,$3,$4,$5,$6,$8,$9,$10,$11,$7}' OFS=';' "$file"

答案2

更短的解决方案是

awk -F',+' -v OFS=, '{$(NF+1)=$7; $7=""; $0=$0; $1=$1}1' file

我不确定是否,+适用于所有awk版本,但至少适用于 GNU awk,也适用于-c兼容模式。

解释:

  • $(NF+1)=$7:首先我们将第 7 个字段添加到行尾(可能$12=$7在本例中)
  • $7="":在下一步中,第 7 个字段被删除(但周围的分隔符保留)
  • 要删除分隔符,我们需要重新设置整个记录(通过$0=$0)将多个逗号视为字段分隔符(这是通过 完成的-F',+',这里+表示一次或多次),并且还通过重新排列当前记录以$1=$1使用先前设置的输出字段强制重建行分隔符(由选项设置-v OFS=,
  • 所有洗牌完成后,我们准备打印结果1

输入示例:

1,2,3,4,5,6,7,8,9,10,11

输出

1,2,3,4,5,6,8,9,10,11,7

答案3

如果您使用 进行打印OFS=,那么字段之间没有分隔符,您可以简单地将 的值保存$7在变量中,设置$7为空并直接打印行和变量。您不需要指定所有字段:

$ cat file
1,2,3,4,5,6,7,8
$ awk -F, -vOFS= '{k=$7; $7=""; print $0,k}' file 
12345687

答案4

几个awk变体(假设您的文件位于变量内$file

  • 在这里,您可以循环所有列,使用字段分隔符(OFS)进行打印,并在行尾打印记录终止符(ORS)。

    awk  -F',' -v OFS=,                                \
    '{for(i=1;i<=NF;i++) if (i!=7) printf "%s",$i OFS; \
    printf "%s",$7;printf ORS}' "$file"
    
  • 这里使用正则表达式和gensub()功能

    gawk -F',+' -v OFS=, '{$0=gensub(/\s*\S+/,"",7) OFS $7}1' "$file"
    

    杀戮第 7 个字段并将其打印在行尾。

    • $0是整个记录
    • $n是第 n记录
    • NF是当前行的字段数
    • OFS输出字段分隔符
    • ORS输出记录终止符
    • 1true这是对 awk 说并打印默认值 ( )的技巧$0

更新...

我几乎忘记了,有可能移动第 7之后的所有列。

awk  -F',' -v OFS=, '{tmp=$7; for(i=7;i<=NF;i++) $i=$(i+1); $NF=tmp}1 ' "$file"

相关内容