在一行上匹配两个图案并在两列中打印

时间:2018-12-14 16:57:11

标签: awk filter grep

我大约有几百个CSV文件。这些CSV文件的定义不同,我不想手动将所有CSV文件合并为一种格式。

我想从文件中获得两个不同的东西-A和B,我可以将它们与正则表达式匹配。我想一次将它们都匹配-因此将只打印同时包含这两种内容的行。我知道该怎么做,而且我已经看到很多SO帖子都回答了如何做。

但是我不知道如何在没有剩余行的情况下仅打印A B。我不知道这两件事将以什么顺序或以哪几列显示,所以我不知道如何(或什至可以使用)awk。

示例:

(匹配A [0-9],B [0-9])

A0 B0 C0
B1 C1 D1
E2 C2 A2
C3 F3 F3
B4 F4 A4

结果:

A0 B0
A4 B4

2 个答案:

答案 0 :(得分:3)

第一个解决方案: :使用match的{​​{1}}功能。按照OP显示的示例,它将按字母A到B的顺序输出。

awk


第二个解决方案: 该解决方案将不在乎字母A和B,因此它们以相同的顺序排列。

awk '
match($0,/A[0-9]+/){
  val=substr($0,RSTART,RLENGTH)
  if(val && match($0,/B[0-9]+/)){
     print val,substr($0,RSTART,RLENGTH)
  }
}'  Input_file


第三个​​解决方案: :考虑到您需要按输出中从A到B的顺序使用它们,那么以下操作可能会有所帮助。

awk '
{
  for(i=1;i<=NF;i++){
    if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){
       val=val?val OFS $i:$i
    }
  }
  if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
    print val
  }
  val=""
}
END{
  if(val ~ /A[0-9]+/ && val ~ /B[0-9]+/){
    print val
  }
}'   Input_file

注意: :从awk ' { for(i=1;i<=NF;i++){ line=$i sub(/[0-9]+/,"",line) if($i ~ /A[0-9]+/ || $i ~ /B[0-9]+/){ array[tolower(line)]=$i } } if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){ print array["a"],array["b"] } delete array } END{ if(array["a"] ~ /A[0-9]+/ && array["b"] ~ /B[0-9]+/){ print array["a"],array["b"] } }' Input_file 文档中添加有关已使用功能的信息,例如-> man awkmatch,{{1 }}和tolower

  

match(s,r [,a])返回s中常规位置   出现表达式r;如果不存在r,则返回0,并设置表达式的值   RSTART                           和RLENGTH。请注意,参数顺序与〜运算符的顺序相同:str〜re。如果提供了数组a,   是                           清除,然后用匹配对应的s部分填充元素1至n   带括号的                           r中的子表达式a的第0个元素包含s中与整个正则表达式r匹配的部分。   子                           脚本a [n,“ start”]和a [n,“ length”]分别在字符串和长度中提供   每                           匹配的子字符串。

     

RSTART由match()匹配的第一个字符的索引; 0,如果   没有匹配。 (这意味着字符索引从1开始。)

     

长度   match();匹配的字符串的长度;如果没有匹配,则为-1。

     

tolower(str)返回字符串str的副本,其中所有   str中的大写字符转换为它们对应的字符   小写                                  同行。非字母字符保持不变。

答案 1 :(得分:1)

  

但是我不知道如何在没有剩余行的情况下仅打印A B。

好吧,您需要从匹配的行中删除除A和B以外的所有内容,并强制awk重新计算字段($1=$1会这样做)。

awk '/A[0-9]/ && /B[0-9]/ { gsub(/[^AB][0-9]/,""); $1=$1; print }' file