【问题标题】:Awk based filtering of data on a file in LinuxLinux中基于awk的文件数据过滤
【发布时间】:2022-01-04 15:20:39
【问题描述】:

我有一个试图通过 awk 过滤的文件数据,我可以过滤数据,但希望 awk 语句更简单为一行:

文件内容:

Entity Name
Value
Unknown dbs636294051.klm.bet.com: /opt
N/A
Unknown dbs636294051.klm.bet.com: /tmp
N/A
Unknown dbs636294051.klm.bet.com: /var
N/A

我的试用:

awk  '!/^N/{ if($2 ~ /klm/) print $2}' file | awk -F":" '{print $1}'

上述方法有效,但我正在寻找是否可以将其修剪到之前的管道:

dbs636294051.klm.bet.com
dbs636294051.klm.bet.com
dbs636294051.klm.bet.com

【问题讨论】:

  • Unknown 在您的输入中代表什么?是字面意义上的Unknown 这个词还是任何你不知道它可能是什么的随机文本或其他什么?
  • @EdMorton,Unknown 是所有关键缺失值的起始行,在这里可以将其视为主要前导字符串。换句话说,它在以Unknown开头的文件中的主要字符串。

标签: linux awk


【解决方案1】:

sub 函数可用于修剪冒号以及 $2 之后的任何内容:

awk '!/^N/ && $2 ~ /klm/ {sub(/:.*$/,"",$2); print $2}' file

【讨论】:

    【解决方案2】:

    您可以编写单个 awk 命令,将字段分隔符设置为 1 个或多个空格或 :,检查字段 1 是否不以 N 开头,并包含 klm

    具体来说,你也可以写^N\/A$

    感谢@Renaud Pacalet 和@Wiktor Stribiżew 的cmets,命令看起来像:

    awk -F'[[:blank:]]+|:' '!/^N/ && $2 ~ /klm/{print $2}' file
    

    部分

    awk -F'[[:blank:]]+|:' '   # Set the field separator to either 1+ spaces or tabs or a semicolon
    !/^N/ && $2 ~ /klm/        # If the record does not start with `N` and field 2 does contain klm
    {print $2}                 # Print the second column
    

    输出

    dbs636294051.klm.bet.com
    dbs636294051.klm.bet.com
    dbs636294051.klm.bet.com
    

    【讨论】:

    • 不错。 -F'[[:space:]]+|:' 可能更安全。
    • 注意不是$2不能以N开头,是完整记录。
    • awk -F'[[:blank:]]+|:' '!/^N/ && $2 ~ /klm/{print $2}' file
    • @Thefourthbird !/^N/$0 核对,整个记录,是的,在开始时。
    • @kulfi 不客气,我还从 Wiktor Stribiżew 和 Renaud Pacalet 那里学到了一些新见解,就像我每天在这里做的那样:-)
    【解决方案3】:

    这是一种快速而肮脏的方法,适用于给定的示例。 如果你有更多的过滤规则,也很容易调整。

    awk -F'[:\\s]' 'NR>1 && $2~/klm/{print $2}' f
    636294051.klm.bet.com
    636294051.klm.bet.com
    636294051.klm.bet.com
    

    更新,另一种方法:

    awk '$2~/klm/ && (($0=$2)+sub(/:.*/,""))' f
    

    【讨论】:

    • \s 是 gawk 特定的,不能在括号内用作 [:space:]
    • /klm/ 匹配任何地方,而不仅仅是字段$2
    • @RenaudPacalet 是的,应该是 `$2~/klm/'
    • @rowboat,你是对的。我的回答中的第二种方法怎么样。 ;-)
    • 亲爱的@Kent,非常感谢您的精彩回答和即时改进,您是宝石人中的一员!
    【解决方案4】:

    awk '/Unknown/{gsub(/:/,"",$0);print $2}' 文件

    【讨论】:

    • 亲爱的@Alejandro,以及出色的方法,这也很好用。
    【解决方案5】:

    当您有两个带有不同字段分隔符的管道 awk 命令时,例如

    awk  '!/^N/{ if($2 ~ /klm/) print $2}' file | awk -F":" '{print $1}'
    

    在这种情况下,您可以使用 split 函数将其转换为单个 awk 命令

    awk  '!/^N/{ if($2 ~ /klm/){split($2,arr,":");print arr[1]}}' file
    

    免责声明:此答案仅适用于将 2 awks 更改为单个,其他改善方法不在此答案的范围内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2012-02-12
      • 2021-12-20
      • 1970-01-01
      • 2014-07-22
      • 1970-01-01
      相关资源
      最近更新 更多