【问题标题】:Print strings of file1 that appears in file2 in awk打印出现在 awk 中的 file2 中的 file1 的字符串
【发布时间】:2019-06-29 06:33:13
【问题描述】:

我想打印 file1 中出现在 file2 中的编程语言、它在 file2 中的对应行号以及 file2 的完整行。

file1 是这样的:

Ruby
Visual Basic
Objective-C
C
R
C++
Basic

file2 是这样的:

5. ab cde fg Java hij kl
2. ab PHP dddf llf 
4. cde fg z o Objective-C oode
8. a12b cde JavaScript kdk
6. ab99r cde Visual Basic llso dkd
1. lkd dsk Ruby kksdk
3. Python dsdls
9. CSS dkdsk
4. Jdjdj C Jjd Kkd
12. Iiii Jjd R Hhd
5. Jjjff C++ jdjejd
7. Jfjfjdoo Uueye Basic Jje Tasdk

我想得到这个输出:

 6|Ruby|1. lkd dsk Ruby kksdk
 5|Visual Basic|6. ab99r cde Visual Basic llsodkd            
 3|Objective-C|4. cde fg z o Objective-C oode
 9|C|4. Jdjdj C Jjd Kkd  
 10|R|12. Iiii Jjd R Hhd 
 11|C++|5. Jjjff C++ jdjejd
 12|Basic|7. Jfjfjdoo Uueye Basic Jje Tasdk 

其中 6,5 和 3 是文件 2 中出现“Ruby”、“Visual Basic”和“Objective-C”的行号。

到目前为止,我已经尝试过使用下面的代码,但该代码仅在文件 2 与文件 1 比较时具有完全匹配列表时才有效。

awk 'NR == FNR{a[$0];next} ($0 in a)' file1 file2

在这种情况下,file2 中的编程语言在前后都有一些文本,我被困在如何获得我想要的输出。

提前感谢您的帮助。

【问题讨论】:

  • 作为测试用例,您应该在 file1 中包含 CC++ 以验证编程语言是否被视为完整字符串,而不是部分字符串或正则表达式,并且您应该在 file2 中包含以下行包含多种编程语言,以确保脚本不只是找到一种。还将Basic 添加到file1 并显示如果file1 同时包含BasicVisual Basic 时的预期输出应该是什么
  • @EdMorton 非常感谢您关于添加 C、C++ 和 Basic 的建议。我还在两个文件和 Ravinder 的代码中都包含了 R,它可以正确打印除 Basic 之外的所有代码,因为它打印出现 Visual Basic 和 Basic 本身的行。对于 Basic 应该只打印 Basic 出现而不是 Visual Basic 的行
  • 不客气。但是,您应该将提到的案例添加到问题中的示例中,而不仅仅是添加到桌面上的文件中。
  • @EdMorton 我已经编辑了 file1、file2 和输出。感谢您的建议

标签: awk


【解决方案1】:

您能否尝试关注(根据@Ed Morton 先生的建议更改了index 在代码中的使用)。

awk -v OFS='|' '
FNR==NR{
  a[$0]
  next
}
{
  for(i in a){
     if(index(" "$0" "," "i" ")){
         print FNR,i,$0
     }
  }
}
'  Input_file1  Input_file2 | sort -t'|' -nr

输出如下。

6|Ruby|1. lkd dsk Ruby kksdk
5|Visual Basic|6. ab99r cde Visual Basic llso dkd
3|Objective-C|4. cde fg z o Objective-C oode

说明:现在为上述代码添加说明。

awk -v OFS='|"' '                           ##Starting awk program here.
FNR==NR{                                   ##Checking condition FNR==NR which will be TRUE when first Input_file is being read.
  a[$0]                                 ##creating an array named a whose index is $0 and value is $0.
}
{                                          ##Starting block here.
  for(i in a){                             ##Starting a for loop here.
     if(index(" "$0" "," "i" ")){                   ##checking if value of a[i] array present in current line.
         print FNR,i,$0             ##If above is TRUE then print FNR"|"i"|"$0 as per OP need.
     }
  }
}
'  file1  file2 | sort -t'|' -nr           ##Mentioning Input_files names here and passing its output into sort command and sorting it with reverse order.

【讨论】:

  • 非常感谢您的帮助。它工作正常,唯一的问题是按照 Ed Morton 的建议,我在 file1 和 file2 中添加了 C、C++ 和 Basic。打印对于 C 和 C++ 是正确的,但对于 Basic 打印出现 Basic 的 file2 的行和一些其他文本,但也会打印出现 Visual Basic 的行。如何解决这个问题?
  • @GerCas 正在努力,几分钟后也会添加该解决方案。
  • 我按照 Ed Morton 的建议编辑了 file1、file2 和 outpu。感谢您的帮助。
【解决方案2】:

使用 GNU awk for sorted_in 首先搜索最长的语言(例如Visual Basic),并在找到它们时从当前行中删除它们,以便它们中的较短语言(例如Basic)可以'在其中找不到:

$ cat tst.awk
BEGIN { OFS="|" }
NR==FNR {
    lengths[$0] = length($0)
    next
}
{
    line = " " $0 " "
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (lang in lengths) {
        if ( s = index(line," "lang" ") ) {
            print FNR, lang, $0
            line = substr(line,1,s) substr(line,s+1+lengths[lang])
        }
    }
}

$ awk -f tst.awk file1 file2
3|Objective-C|4. cde fg z o Objective-C oode
5|Visual Basic|6. ab99r cde Visual Basic llso dkd
6|Ruby|1. lkd dsk Ruby kksdk

$ cat file1
Ruby
Visual Basic
Objective-C
C
C++
Basic

【讨论】:

  • 感谢您的解决方案。当字符串有空格时,它似乎可以很好地处理这种情况。不需要基于行号的排序,只需按照与 file1 相同的顺序打印输出即可。我看到你的排序方法不同,所以我不知道如何从你的代码中删除它而不影响它。
  • 它不是根据行号排序,而是根据编程语言字符串的长度进行排序,并且 IS REQUIRED 以便从一行中找到/删除 Visual Basic在它在同一行上查找 Basic 之前。这就是为什么它找不到Basic 作为Visual Basic 的一部分的关键。
  • 好的。感谢您的澄清和再次提供帮助。
猜你喜欢
  • 2013-03-04
  • 2018-11-08
  • 2021-06-27
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多