![如何将多个管道 awk 命令合并为单个 awk 命令](https://linux22.com/image/183564/%E5%A6%82%E4%BD%95%E5%B0%86%E5%A4%9A%E4%B8%AA%E7%AE%A1%E9%81%93%20awk%20%E5%91%BD%E4%BB%A4%E5%90%88%E5%B9%B6%E4%B8%BA%E5%8D%95%E4%B8%AA%20awk%20%E5%91%BD%E4%BB%A4.png)
我正在编写一个脚本来过滤包含以下内容的文件
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
- 字段分隔符正则表达式将第一个字段与or
$1
之后的所有字段分开:
=
- gsub 删除所有前导和尾随空格
- 之前的正则表达式
{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