求助:提取两文件共有的:name及其下方关联行的Bash实现
问题
现有两个输入文件,需提取两文件中共同的:name条目,同时输出file1中该:name下方所有的./name/of/file格式的行。尝试了如下awk命令:
awk '/:name1/{flag=1} flag;/ /{flag=0}' /path/of/input/file1
但该命令仅能输出第一个关联行,无法获取全部内容。
输入文件1
:name1 ./name/of/file [logfile] [ error in file coming since Day : 1 ] ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name2 ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name3 ./name/of/file [logfile] [ error in file coming since Day : 24 ] ./name/of/file [logfile] [ error in file coming since Day : 24 ] :name4 ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] :name5 ./name/of/file [logfile] [ error in file coming since Day : 6 ] ./name/of/file [logfile] [ error in file coming since Day : 6 ]
输入文件2
:name1 :name3 :name4
当前输出
:name1 ./name/of/file [logfile] [ error in file coming since Day : 1 ]
期望输出
:name1 ./name/of/file [logfile] [ error in file coming since Day : 1 ] ./name/of/file [logfile] [ error in file coming since Day : 1 ] :name3 ./name/of/file [logfile] [ error in file coming since Day : 24 ] ./name/of/file [logfile] [ error in file coming since Day : 24 ] :name4 ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ] ./name/of/file [logfile] [ error in file coming since Day : 3 ]
解决方案
原命令的问题在于/ /{flag=0}会匹配所有包含空格的行,而目标文件行本身就有空格,导致只输出第一行就关闭了输出标志。正确的思路是先将file2中的所有目标:name存入数组,再遍历file1,根据当前行是否属于目标name来控制输出。
命令实现
如果不需要缩进,使用以下命令:
awk 'NR==FNR {names[$0]=1; next} /^:/ {current=$0; print_flag=names[current]?1:0} print_flag && /^(\.\/|:/)' file2 file1
如果需要和期望输出一致的缩进格式,使用这个命令:
awk 'NR==FNR {names[$0]=1; next} /^:/ {current=$0; print_flag=names[current]?1:0; if(print_flag) print $0} print_flag && /^\.\// {print " " $0}' file2 file1
命令说明
NR==FNR {names[$0]=1; next}:处理file2时,将每一行的:name存入names数组,然后跳过后续逻辑,继续读取下一行。/^:/ {current=$0; print_flag=names[current]?1:0; if(print_flag) print $0}:在file1中遇到以:开头的行时,更新当前name,判断该name是否在names数组中,设置输出标志print_flag;如果是目标name,直接输出该行。print_flag && /^\.\// {print " " $0}:当输出标志为1时,对所有以./开头的行添加4个空格缩进后输出。
内容的提问来源于stack exchange,提问作者aastha
相关产品推荐
相关产品推荐

