【问题标题】:exclude columns from awk从 awk 中排除列
【发布时间】:2016-07-25 19:46:12
【问题描述】:

我正在尝试删除几列,然后删除文件内容的唯一性。我要删除的列是月、日、时间和纪元时间;这些在每一行中都是不同的,不能让我对文件内容进行唯一化。

sample.log 的示例内容:

Jun  5 05:13:13 AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
Jun  5 05:13:14 AAA AAA AAAA 1433495594.306612 XXXX CCCC CCCC AAAA SDDDD DFFFFF222
Jun  5 05:13:13 AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
Jun  5 05:13:15 AAA AAA AAAA XXXXX 1433495596.306614 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
Jun  5 05:13:16 AAA AAA AAAA XXXXX 1433495597.306615 XXXX CCCC CCCC AAAA SDDDD DFFFFF333
Jun  5 05:13:17 AAA AAA AAAA XXXXX 1433495598.306616 XXXX CCCC CCCC AAAA SDDDD DFFFFF444

问题:

月份、日期、时间在固定列中,但是纪元时间在第 7 列和第 8 列之间切换。想知道如何处理。

示例输出:

Jun  5 05:13:13 AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
Jun  5 05:13:13 AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
Jun  5 05:13:15 AAA AAA AAAA XXXXX 1433495596.306614 XXXX CCCC CCCC AAAA SDDDD DFFFFF111

如果上面的要求太多,那么如下:

AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
AAA AAA AAAA 1433495593.306611 XXXX CCCC CCCC AAAA SDDDD DFFFFF111
AAA AAA AAAA XXXXX 1433495596.306614 XXXX CCCC CCCC AAAA SDDDD DFFFFF111

我正在按照以下方向尝试,但不是很有帮助。

while read line
    do

seven=$(echo $line |awk '{print $7}')
eight=$(echo $line |awk '{print $8}')

if [[ "$seven" =~ "^[0-9]" ]];then
    #echo "seventh column starts with number"
    echo $line|awk '$1=$2=$3=$7=" " {print}'
else
    #echo "Eighth column starts with number"
     echo $line|awk '$1=$2=$3=$8=" " {print}'
fi
    done < $1

更多示例:

输入文件内容:

Jun  5 05:13:13 AAA BBB CCC 142222222222.000 DDD EEE FFFF
Jun  5 05:13:13 AAA BBB CCC 142222222223.000 DDD EEE FFFF
Jun  5 05:13:14 AAA BBB CCC 142222222224.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE FFFF
Jun  5 05:13:13 AAA BBB CCC XXX 142222222226.000 DDD EEE FFFF

输出:

Jun  5 05:13:13 AAA BBB CCC 142222222223.000 DDD EEE FFFF
Jun  5 05:13:13 AAA BBB CCC 142222222223.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE FFFF

输出:

 AAA BBB CCC  DDD EEE FFFF
 AAA BBB CCC  DDD EEE GGGG
 AAA BBB CCC XXX  DDD EEE GGGG
 AAA BBB CCC XXX  DDD EEE FFFF

【问题讨论】:

  • 请注意,不要说while read line ...; seven=$(echo $line | awk '{print $7}',您可以随时使用while read field1 field2 ... field7 field8
  • 谢谢你的信息,我的真的很丑!

标签: linux bash awk sed


【解决方案1】:

如果我正确理解了这个问题,这里就不需要 Bash,只需 Awk:

% awk '
{
    for (f = 4; f <= NF; ++f) { # Start at column 4
        if (f == 7 || f == 8) { # Treat columns 7 or 8 differently
            if ($f !~ /^[0-9]+\.[0-9]+$/) { # Only print if non-numeric
                printf $f " "
            }
        } else {
            printf $f " "
        }
    }
    printf "\n"
}
' sample.log          
AAA AAA AAAA XXXX CCCC CCCC AAAA SDDDD DFFFFF111 
AAA AAA AAAA XXXX CCCC CCCC AAAA SDDDD DFFFFF222 
AAA AAA AAAA XXXX CCCC CCCC AAAA SDDDD DFFFFF111 
AAA AAA AAAA XXXXX XXXX CCCC CCCC AAAA SDDDD DFFFFF111 
AAA AAA AAAA XXXXX XXXX CCCC CCCC AAAA SDDDD DFFFFF333 
AAA AAA AAAA XXXXX XXXX CCCC CCCC AAAA SDDDD DFFFFF444 

获取唯一行:

% awk '             
{
    for (f = 4; f <= NF; ++f) { # Start at column 4
        if (f == 7 || f == 8) { # Treat columns 7 or 8 differently
            if ($f !~ /^[0-9]+\.[0-9]+$/) { # Only print if non-numeric
                printf $f " "
            }
        } else {
            printf $f " "
        }
    }
    printf "\n"
}
' sample2.log | sort -u
AAA BBB CCC DDD EEE FFFF 
AAA BBB CCC DDD EEE GGGG 
AAA BBB CCC XXX DDD EEE FFFF 
AAA BBB CCC XXX DDD EEE GGGG 

关于处理%s...

如果您的输入文件包含% 符号,根据您的评论,您需要先对这些符号进行转义,然后再将它们传递给printf。你可以用这样的function 来做到这一点......

% awk '             
function escape_percents(s) 
{ 
    gsub("%", "%%", s) 
    return s
}

{
    for (f = 4; f <= NF; ++f) { # Start at column 4
        if (f == 7 || f == 8) { # Treat columns 7 or 8 differently
            if ($f !~ /^[0-9]+\.[0-9]+$/) { # Only print if non-numeric
                printf escape_percents($f) " "
            }
        } else {
            printf escape_percents($f) " "
        }
    }
    printf "\n"
}
' sample2.log | sort -u
AAA BBB CCC DDD %E%E%E FFFF 
AAA BBB CCC DDD %E%E%E GGGG 
AAA BBB CCC XXX DDD %E%E%E FFFF 
AAA BBB CCC XXX DDD %E%E%E GGGG 

【讨论】:

  • awk:cmd。 line:9: (FILENAME=samplelog FNR=51452) 致命:没有足够的参数来满足格式字符串 `%ERROR: ' ^ 用完这个
  • 注意printf "\n"也可以说成print ""
  • @RandomUser:告诉我你是如何解决这个问题的! :-)
  • @fedorqui:是的,我考虑过这种实现,但为了清晰起见,我更喜欢明确的\n
  • @RandomUser 这可能有问题,因为您在寻找唯一值时会将%EE 混为一谈。请参阅我更新的解决方案以了解不同的方法...
【解决方案2】:

一个非常基本的方法是检查字段的格式:如果它由数字 + . + 数字组成,那就是那个!

awk '{$1=$2=$3=""
      if ($7 ~ /^[0-9]+\.[0-9]+$/) {$7=""}
      else {$8=""}
     } 1' file

请注意,这会在周围留下一些额外的空格,因为当您清空一个字段时,交错的 FS 会保留在那里。要彻底删除列,请查看 Ed Morton 对 Print all but the first three columns 的回答。


为确保每列第 1、2、3 和最后一个块不重复,请使用 awk '!uniq[$0]++' file 方法:

awk '!uniq[$1 $2 $3 $(NF-4) $(NF-2) $(NF-1) $NF]++{$1=$2=$3=""
      if ($7 ~ /^[0-9]+\.[0-9]+$/) {$7=""}
      else {$8=""}
     } 1' file

【讨论】:

  • @RandomUser 你为什么需要它?说明你想做什么,因为很可能awk 能够做到。
  • 我想找到唯一的日志(每个日志只出现一次),但是 day,date,epoch 不允许我这样做。
  • @RandomUser 好的,使用 awk 应该很容易。提供一个minimal reproducible example 以便我检查。也就是说,样本输入(您已经拥有)和所需的输出。
  • @RandomUser 好的!添加了确保不出现重复行的方法。
【解决方案3】:

如果历元时间之后的列保持不变,那么最简单的方法是只操作 NF。

使用更多示例中的输入:

awk '{NewLine=$4; 
for(i=(NF-5);i>=0;i--){
if(i!=3){
NewLine=NewLine" "$(NF-i)
}
}
print NewLine
}' Sample.log | sort | uniq

使用输入

Jun  5 05:13:13 AAA BBB CCC 142222222222.000 DDD EEE FFFF
Jun  5 05:13:13 AAA BBB CCC 142222222223.000 DDD EEE FFFF
Jun  5 05:13:14 AAA BBB CCC 142222222224.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE GGGG
Jun  5 05:13:13 AAA BBB CCC XXX 142222222225.000 DDD EEE FFFF
Jun  5 05:13:13 AAA BBB CCC XXX 142222222226.000 DDD EEE FFFF

你会得到

AAA BBB CCC DDD EEE FFFF
AAA BBB CCC DDD EEE GGGG
AAA BBB CCC XXX DDD EEE FFFF
AAA BBB CCC XXX DDD EEE GGGG

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 2021-04-23
    • 2019-01-26
    • 2012-03-27
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多