如何用awk输出file1中在file2出现的编程语言及对应信息
解决方法:匹配file1中的编程语言在file2中的出现行
你的问题核心是需要匹配file1中的编程语言作为独立单词出现在file2的行中,而不是整行匹配。原来的awk代码只能检查file2的整行是否在file1中,所以无法满足需求。以下是针对你需求的解决方案:
最终awk代码
NR == FNR { # 从file1中提取所有编程语言(包括带空格的如Visual Basic) while (match($0, /([A-Za-z0-9-]+( [A-Za-z0-9-]+)?)/, m)) { lang = m[1] langs[lang] = length(lang) $0 = substr($0, RSTART + RLENGTH) } next } { # 按语言长度从长到短遍历,优先匹配长语言(避免Basic匹配Visual Basic的行) PROCINFO["sorted_in"] = "@val_num_desc" for (lang in langs) { # 匹配独立单词,防止语言作为其他词的一部分被误匹配 if ($0 ~ "\\<" lang "\\>") { print FNR "|" lang "|" $0 break # 同一行只匹配第一个符合的语言 } } }
使用方式:将上述代码保存为脚本或直接运行:
awk -f script.awk file1 file2
代码解释
处理file1:
- 用正则表达式
([A-Za-z0-9-]+( [A-Za-z0-9-]+)?)提取所有编程语言,包括带空格的(如Visual Basic)和带连字符的(如Objective-C)。 - 将每个语言存入数组
langs,值为语言的长度,用于后续排序。
- 用正则表达式
处理file2:
- 设置
PROCINFO["sorted_in"] = "@val_num_desc",让循环按语言长度从长到短遍历,这样Visual Basic会比Basic先被匹配,避免短语言误匹配包含长语言的行。 - 用
\\<和\\>匹配独立单词(GNU awk支持的单词边界),确保语言是作为单独的词汇出现,而不是其他词的一部分(比如避免C匹配Java中的C)。 - 匹配到后输出
行号|语言|完整行,并break跳出循环,避免同一行输出多个匹配结果。
- 设置
为什么原代码不适用?
你的原代码awk 'NR == FNR{a[$0];next} ($0 in a)' file1 file2是检查file2的整行是否存在于file1的行中,而你的需求是file2的行包含file1中的某个语言作为子串,两者逻辑完全不同,所以无法得到期望结果。
内容的提问来源于stack exchange,提问作者Ger Cas
相关产品推荐
相关产品推荐

