温馨提示:本文翻译自stackoverflow.com,查看原文请点击:linux - Awk, split, and print a range of columns
awk linux split multiple-columns

linux - AWK,拆分和打印一系列列

发布于 2020-04-08 11:15:54

我想用现有文件中的选择列创建一个新文件。我想选择基于“ X”的行,然后按原样打印列1、2、4和5。然后,我想基于定界符“:”将第10列拆分为最后一列(50),并仅提取每个列的第一部分。

示例:第10到50列看起来像-> 10:a:b:c:d:e:f (我只希望每个列中都包含“ 10”)。

到目前为止,我有以下内容,但是我不确定如何为拆分和打印a [1]部分做一定范围的列,所以这里我只有第10列,但是我希望它一直做同样的事情到第50列。

输入示例:

X 2 3 4 5 6 7 8 9 10:a:b:c 11:d:e:f 12:g:h:i (all the way to 50)

示例输出:

X 2 4 5 10 11 12 (all the way to 50)

码:

awk '$1 == "X" {print $1, $2, $4, $5, split($10,a,":"), a[1]}' file.txt > test.txt

查看更多

提问者
Sarah
被浏览
96
ghoti 2020-02-06 01:44

我想我会有所不同。与其在数组中的字段10到50中捕获第一个用“:”定界的子字段,不如直接重写这些字段。

$1 == "X" {
  $3=""
  for (i=6; i<=9; i++)
    $i=""
  for (i=10; i<=NF; i++)
    $i=substr($i,0,index($i,":")-1)
  print
}

$3这里的处理有点弱;awk没有消除列的真正解决方案。如果您无法处理额外的分隔符,则可能需要更详细的说明:

$1 == "X" {
  s=""
  for (i=10; i<=NF; i++)
    s=s OFS substr($i,0,index($i,":")-1)
  print $1,$2,$4,$5 s
}

此解决方案在最后一个命令前缺少逗号,s因为OFS将作为该字符串的第一个字符包含在内。这是一个优化,以避免不必要的测试,但是如果您愿意,也可以转而避免使用临时变量:

$1 == "X" {
  printf "%s", $1 OFS $2 OFS $4 OFS $5
  for (i=10; i<=NF; i++)
    printf "%s", OFS substr($i,0,index($i,":")-1)
  printf ORS
}

我们printf在这里使用以避免ORS的虚假出现。

我这样测试:

$ cat input
X 2 3 4 5 6 7 8 9 10:a:b 11:c:d 12:e:f:g
$ awk -f test.awk input
X 2 4 5 10 11 12