awk 如何在 for 循环中连接字符串并从 END 部分打印

awk 如何在 for 循环中连接字符串并从 END 部分打印

问题: ”A" 从 END 部分打印的变量只有最后找到的行而不是所有行

文件1:

pattern .........
irrelevant text
irrelevant text
pattern .........
pattern .........
irrelevant text

awk代码:

awk '{ for (i=1; i<=NR; i++)
       if ($i ~ /^pattern/) a+=$0 
     }
     END {print $a}' file1

从 END 部分我只想打印带有图案的行

答案1

您似乎想要收集与特定模式匹配的所有行,然后在最后打印它们。

你可以这样做

awk '/^pattern/ { a[++n] = $0 }
     END { for (i = 1; i <= n; ++i) print a[i] }' file

这用作a数组并将与模式匹配的每一行添加为数组中的新条目。最后,循环迭代 的条目a并打印每个条目。

如果您想在第一列中查找确切的文字字符串,pattern而不是针对整行匹配正则表达式,请使用$1 == "pattern"as 条件。

但是,如果这是全部你想做的,那么使用就更容易

awk '/^pattern/' file

或者,如果您想匹配pattern第一列中的文字字符串,

awk '$1 == "pattern"' file

这将为与模式匹配的每一行调用默认操作,或者pattern如果您使用第二个变体,则将其包含为第一列。 “默认操作”是打印该行。


在 中awk,将是一个算术运算,它将当前行a += $0的值递增,解释为数字。a要将 line 作为字符串连接到变量a,您可以使用a = a $0, 或者如果您想在附加的字符串之前a = a ORS $0插入换行符( 的默认值)。ORS但我相信这些都不是您想要在这里做的。

答案2

您的代码有几个问题:

  1. 您想要访问文件的所有行以测试匹配模式,但您是在一个规则块 ( { ... }) 中执行此操作。但是所有规则都会被处理对于文件的每一行,并且在这样的规则中,您只能访问当前处理的行的内容。代码

    { for (i=1; i<=NR; i++)
       if ($i ~ /^pattern/) a+=$0 
    }
    

    因此会尝试(对于文件的所有行,因为它前面没有条件)来测试领域数字 1 到NR- 哪里NR文件中当前行的行号,不是当前行的字段数NF,而是尝试追加整个当前行a每次发生这种情况时都指向变量。如果模式确实只能出现在正则表达式所暗示的行的开头(由于锚),这可能不会弄乱结果,^但至少效率极低。

  2. 在尝试将当前行附加到 时a,您编写

    a+=$0
    

    然而,只有当该行(或至少第一个空格分隔的字段)可以被正确解释为数字时,这才是明确定义的,在这种情况下,这a将是仅包含/开头的所有行上的数字之和文件中出现的单个数字。如果没有一行可以被解释为数字,则a最后的值为“0”。

  3. END块中,您声明

    print $a
    

    然而,这将打印字段编号a当前行的内容,而不是变量的内容a。然而,由于您的变量a是“0”(如第 2 点中所述),因此这将指整个当前行(也称为$0)。并且由于对块中字段编号的引用END始终引用文件的最后一行(由于文件末尾缺少“当前”行),因此此语句将不可避免地打印文件的整个最后一行,而不会打印其他内容。

由于您似乎只对打印与特定模式匹配的行感兴趣,因此使用grep专用于此类任务的工具可能会更容易。

答案3

如果您只想打印第一个字段为 的所有行pattern,则无需将内容存储在内存中,您可以只打印找到的每一行:

awk '$1=="pattern"' file

甚至

grep -w '^pattern' file

相反,如果您想打印每一行任何该行的字段是pattern,使用:

awk '{ for(i=1; i<=NF; i++){ if($i=="pattern"){ print; next}}}' file

或者,如果您只是寻找字段值的情况开始pattern但之后可以有其他字符(这是您的代码所尝试的),如果您只想要第一个字段,请使用它:

awk '$1~/^pattern/' file

这适用于任何领域:

awk '{ for(i=1; i<=NF; i++){ if($i~/^pattern/){ print; next}}}' file

答案4

如果我正确理解你的问题,你想要连接所有与 匹配的行^pattern,所以这将满足你的需要:

echo $(grep '^pattern' infile)

awk与:相同

echo $(awk '/^pattern/' infile)

awk仅使用:

awk '/^pattern/{ line = (line? line FS $0: $0) }  END{ print line }' infile

相关内容