将一个文件搜索到另一个文件,打印匹配和下一行

时间:2018-01-17 22:03:21

标签: bash awk grep

这是我的问题: 我有两个文件,一个有名字(大约1k行,没有重复)

File_Names

A
C
F

第二个带有名称和数据的文件(大约100k行,没有重复)

File_Data

A
Data_A
B
Data_B
C
Data_C
D
Data_D
E
Data_E
F
Data_F

我需要从名称搜索到数据文件,打印结果和下一行。

类似的东西:

A
Data_A
C
Data_C
F
Data_F

我有找到数据文件名称的部分,但仍无法打印下一行

awk 'FNR==NR{
        a[$1]++;
        next}
        a[$1]
' File_Names File_Data

返回

A
C
F

这是我所保留的代码的一部分,因为我已经尝试了其他代码,例如

awk 'FNR==NR{
    a[$0]=FNR;i=FNR;next}
($0 in a){
    t=$0;
    getline;b[a[t]]=$0}
END{
    for(k=1;k<=i;k++)print b[k]
}'

添加/删除行:

- {x=NR+1}(NR<=x){print}
- {getline;print;}

还尝试使用grep with

grep -f File_Names File_Data

但仍然没有。对不起重复的问题,但可用的解决方案对我不起作用。 提前谢谢。

2 个答案:

答案 0 :(得分:6)

grep 解决方案:

grep -A1 --no-group-separator -xf File_Names File_Data
  • A num - 在匹配行
  • 后打印num行尾随上下文
  • --no-group-separator - 不要在行组之间打印分隔符

输出:

A
Data_A
C
Data_C
F
Data_F

答案 1 :(得分:1)

这是一个简单的awk解决方案:

$ awk 'NR==FNR{a[$0]; next} $0 in a{print; getline; print}' File_Names File_Data
A
Data_A
C
Data_C
F
Data_F

这可能会限制内存中a数组的大小,但我预计1000个密钥不会是一个大问题。它还有一个潜在的竞争,如果你有一行数据也是一个文件名,输出将是不稳定的。您可以通过确保仅在File_Data中的奇数行上检查文件名来保护它:

$ awk 'NR==FNR{a[$0]; next} FNR%2 && $0 in a{print; getline; print}' File_Names File_Data

请注意,你可以单独使用bash做同样的事情,而不依赖于awk,尽管它几乎不会表现得很好:

$ declare -A FN; while IFS= read -r x; do FN[$x]=1; done < File_Names
$ while IFS= read -r x; do IFS= read -r y; [[ -n "${FN[$x]}" ]] && printf '%s\n%s\n' "$x" "$y"; done < File_Data
A
Data_A
C
Data_C
F
Data_F

这取决于declare -A(关联数组)的bash版本4或更高版本。第一个循环使用文件名填充$FN数组的键,第二个循环逐步检查密钥是否存在,如果找到密钥则打印结果。