我有两个文本文件。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”开头),包括此行及之后的行。Text-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.+' *