如何将多个管道 awk 命令合并为单个 awk 命令

如何将多个管道 awk 命令合并为单个 awk 命令

我正在编写一个脚本来过滤包含以下内容的文件

a:10
b:20
c:60
# comment
{{# random mustache templating}}
d=4
e=6

得到的输出看起来像

a
b
c
d
e

这是我的命令

cat filename.txt | awk '{$1=$1;print}' | awk -F'{{' '{print $1}' | awk -F'=' '{print $1}' | awk -F':' '{print $1}' | awk -F'#' '{print $1}' | awk /./

目的:

  • 删除行中出现字符“=”或“:”的所有内容。
  • 删除以“{{”开头的行以删除模板。
  • 修剪每行开头和结尾的空格。
  • 删除所有空白行。

由于我是 bash 新手,如何才能使这个命令更短?

答案1

字段分隔符可以是完整的正则表达式,所以

awk -F'[:#=]' '!/^{{/ && length($1) > 0 { split($1, a, " "); print a[1] }' filename.txt

就足够了:“:”、“#”、“=”中的任何一个都将充当分隔符。我们排除以“{{”开头的行,匹配$1非空的行,$1在空格上分割,并打印第一个结果字段。

答案2

把事情简单化:

$ awk 'NF && ($1 !~ /^(#|\{+)/) { sub(/[:=].*/,""); print $1 }' file
a
b
c
d
e

答案3

为了实现上面的结果,我只是使用正则表达式作为字段分隔符,使用正则表达式来选择行并{print $1}打印第一列。

我在您的示例中没有看到前导空格或空行,但如果您需要处理这些,请参阅下面我对此命令的变体。

awk -F'[:=]' '!/^[#{]/{print $1}' filename.txt

结果:

a
b
c
d
e

如果前导或尾随有空格,则以下方法可能有效。不过,我承认,在没有看到示例的情况下,我很难想象。

awk -F'[:=]' '{gsub(/^\s+|\s+$/,"",$1)} !/^[#{]/{print $1}' filename.txt

为了涵盖所有可能的情况,根据您的评论,我修改了该示例。现在,我们有前导和尾随空格以及空行。

a:10
b :20
  c:60
# comment

 {{# random mustache templating}}
d=4
e =6   

这是处理这个问题的稍微改变的命令:

awk -F'[:=]' '{gsub(/^\s+|\s+$/,"",$1)} !/^[#{]/ && !/^$/{print $1}' filename.txt
  1. 字段分隔符正则表达式将第一个字段与or$1之后的所有字段分开:=
  2. gsub 删除所有前导和尾随空格
  3. 之前的正则表达式{print $1}删除所有以 a#或开头的行{,以排除注释、“模板”和空行。

这会产生以下结果从改编的例子:

a
b
c
d
e

答案4

也许这会帮助你达到预期的结果

#!/bin/bash

dynamic_array=()

while read -r line 
do 
    var=$(echo "$line" | cut -c 1)    
    if ! { [ "$var" = '#' ] ||  [ "$var" = '{' ] || [ "$var" = '}' ]; }
    then
                 dynamic_array+=("$var")   
    fi 
done < A.txt

str_array_value="${dynamic_array[*]}" ; echo "$str_array_value" | tr ' ' '\n' | awk '!seen[$0]++'

输出 :

a   
b   
c    
d
e

相关内容