经过多次 grep 后打印以“D”开头的多行

经过多次 grep 后打印以“D”开头的多行

我有两个文本文件。Text-file-1 包含字符串(每行一个字符串);

C 010
C 020
C 024
.
.
.

Text-file-2包含以下格式的数据;

C 005 Carbon
D Carbon 1
D Carbon 2
D Carbon 3
D Carbon 4
C 010 Hydrogen
D Hydrogen 1
D Hydrogen 2
C 017 Oxygen
D Oxygen 1
C 020 Nitrogen
D Nitrogen 1
D Nitrogen 2
D Nitrogen 3
C 024 Sulphur
D Sulphur 1
D Sulphur 2
.
.
.

Text-file-1 包含 30 行,但 Text-file-2 包含大量数据,格式与我提到的相同。我可以使用以下命令 grep Text-file-1 中找到的 Text-file-2 中的文本;

awk 'NR==FNR { A[$2]=1; next }; A[$2]' Text-file-1 Text-file-2 > filename

此脚本的输出

C 010 Hydrogen
C 020 Nitrogen
C 024 Sulphur
.
.
.

我的期望输出是;

C 010 Hydrogen
D Hydrogen 1
D Hydrogen 2
C 020 Nitrogen
D Nitrogen 1
D Nitrogen 2
D Nitrogen 3
C 024 Sulphur
D Sulphur 1
D Sulphur 2
.
.
.

现在,我需要此命令的扩展,它可以打印所有行(以“D”开头),包括此行及之后的行。T​​ext-file-2 中的所有行都以字母(C 或 D)开头。这个字母对我来说没用,但我保留了它。请帮忙。

答案1

这是一个awk可以完成您想要的操作的脚本:

awk '
  NR==FNR { C[$2]=1; next }
  $1 == "C" { if (C[$2] == 1) { print; D[$3]=1 } }
  $1 == "D" { if (D[$2] == 1) print }
' f1 f2

例子

这是一些示例数据。

$ cat f1
C 010
C 020
C 024

$ cat f2
C 005 Carbon
D Carbon 1
D Carbon 2
D Carbon 3
D Carbon 4
C 010 Hydrogen
D Hydrogen 1
D Hydrogen 2
C 017 Oxygen
D Oxygen 1
C 020 Nitrogen
D Nitrogen 1
D Nitrogen 2
D Nitrogen 3
C 024 Sulphur
D Sulphur 1
D Sulphur 2

结果

$ awk '
>   NR==FNR { C[$2]=1; next }
>   $1 == "C" { if (C[$2] == 1) { print; D[$3]=1 } }
>   $1 == "D" { if (D[$2] == 1) print }
> ' f1 f2
C 010 Hydrogen
D Hydrogen 1
D Hydrogen 2
C 020 Nitrogen
D Nitrogen 1
D Nitrogen 2
D Nitrogen 3
C 024 Sulphur
D Sulphur 1
D Sulphur 2

您可以将awk脚本放入它自己的文件中,如下所示cmd.awk

NR==FNR { C[$2]=1; next }
$1 == "C" { if (C[$2] == 1) { print; D[$3]=1 } }
$1 == "D" { if (D[$2] == 1) print }

然后像这样运行它:

$ awk -f cmd.awk f1 f2
C 010 Hydrogen
D Hydrogen 1
D Hydrogen 2
C 020 Nitrogen
D Nitrogen 1
D Nitrogen 2
D Nitrogen 3
C 024 Sulphur
D Sulphur 1
D Sulphur 2

答案2

这是另一种可能的解决方案,使用sed

while read str; do sed -n "/^$str/,/^C/ {/^$str/p;/^D/p}" Text-file-2; done < Text-file-1

请注意,将 shell 变量替换为sed表达式时应谨慎使用。在这种情况下,这是可以的,因为Text-file-1包含简单的字母数字字符串,但如果 shell 变量包含任何需要在 sed 表达式中转义的“特殊”字符,它将失败。

答案3

您的愿望似乎与当前可能实现的目标相冲突。

如果要从两个文件中打印 D,请使用以下命令:cat file1 file2 | grep -E '^D.+'

问题是,如果您执行 cat 操作,则一旦进行管道传输,您将不再知道文件名,因此您必须执行以下操作:grep -El '^D.+' *

相关内容