如何使用 AWK 查找和匹配列中的精确字符串?

How to find and match an exact string in a column using AWK?

提问人:sirducas 提问时间:6/13/2022 最后编辑:RavinderSingh13sirducas 更新时间:6/24/2022 访问量:1243

问:

我在匹配我想使用 .awk

我有一个名为“sup_groups.txt”的文件,其中包含:
(结构为:“group_name:pw:group_id:user1<,user2>...”)

adm:x:4:syslog,adm1
admins:x:1006:adm2,adm12,manuel
ssl-cert:x:122:postgres
ala2:x:1009:aceto,salvemini
conda:x:1011:giovannelli,galise,aceto,caputo,haymele,salvemini,scala,adm2,adm12
adm1Group:x:1022:adm2,adm1,adm3
docker:x:998:manuel

现在,我想提取用户列表中有用户“adm1”的记录并打印第一列(组名),但是您可以看到有一个名为“adm12”的用户,因此当我这样做时:

awk -F: '$4 ~ "adm1" {print $1}' sup_groups.txt

输出为:

adm
admins
conda
adm1Group

该命令当然也会打印那些包含字符串“adm12”的记录,但我不想要这些行,因为我只对用户“adm1”感兴趣。

那么,如何更改此命令,使其仅打印第 1 行和第 6 行(不包括第 2 行和第 5 行)?

非常感谢你,对不起我的英语不好

编辑:感谢您的回答,您给了我解决方案的灵感,我认为这可能与您的解决方案一样有效,但更简单:

awk -F: '$4 ~ "adm,|adm1$|:adm1," {print $1}' sup_groups.txt

基本上,我使用的是涵盖所有情况的 OR,不包括“adm12” 如果您认为这是正确的,请告诉我

评论

0赞 RavinderSingh13 6/13/2022
您有 2 个分隔符,因此您要实际比较哪个字段的值?:,
0赞 sirducas 6/13/2022
是的,我知道,因为这是用户列表,因此它被视为一个字段。我使用-F:因为我知道我需要在用户列表中找到“adm1”
0赞 RavinderSingh13 6/13/2022
行有 4 列(不包括),行也有 4 个字段,所以你想检查第 4 个字段是否有任何值?adm:x:4:syslog,adm1,admins:x:1006:adm2,adm12,manueladm1
0赞 sirducas 6/13/2022
我只想检查第 4 个字段是否包含用户“ADM1”,然后打印该行,但我使用的命令打印也包含 ADM12 的行

答:

0赞 RavinderSingh13 6/13/2022 #1

第一个解决方案:使用 的函数。使用您显示的示例,请尝试以下代码。splitawkawk

awk -F':' '
{
  num=split($4,arr,",")
  for(i=1;i<=num;i++){
    if(arr[i]=="adm1"){
      print
    }
  }
}
' Input_file

解释:为上述内容添加详细说明。

awk -F':' '               ##Starting awk program from here setting field separator as : here.
{
  num=split($4,arr,",")   ##Using split to split 4th field into array arr with delimiter of ,
  for(i=1;i<=num;i++){    ##Running for loop till value of num(total elements of array arr).
    if(arr[i]=="adm1"){   ##Checking condition if arr[i] value is equal to adm1 then do following.
      print               ##printing current line here.
    }
  }
}
' Input_file              ##Mentioning Input_file name here.


第二种解决方案:在 中使用正则表达式和条件。awk

awk -F':' '$4~/^adm1,/ || $4~/,adm1,/ || $4~/,adm1$/' Input_file

或者,如果第 4 个字段根本没有逗号,请尝试以下操作:

awk -F':' '$4~/^adm1,/ || $4~/,adm1,/ || $4~/,adm1$/ || $4=="adm1"' Input_file

解释:将字段分隔符设置为并检查条件,如果第 4 个字段等于 (从 adm1 开始),或者 IT 等于 OR 等于 (以 ,adm1 结尾),则打印该行。:^adm1,,adm1,,adm1$

评论

0赞 sirducas 6/13/2022
您好,感谢您的回答,这个解决方案很好,但不幸的是我无法使用拆分内置功能
0赞 RavinderSingh13 6/13/2022
@sirducas,欢迎您的到来。但是为什么你不能使用:)split
0赞 RavinderSingh13 6/13/2022
@sirducas,对于您的编辑问题,您的情况与我分享的很相似,恕我直言,任何人都会更容易理解,干杯。
0赞 sirducas 6/13/2022
是的,你是对的,但是如果该行包含唯一的 ADM1 用户怎么办?比如“<......>:adm1“ ?(基本上没有最后的逗号)
1赞 sirducas 6/13/2022
是的,好的,完美的。对不起,我只是 AWK 的新手。非常感谢你这个命令完成工作。
0赞 kvantour 6/13/2022 #2

这应该可以解决问题:

$ awk -F: '"," $4 "," ~ ",adm1," { print $1 }' file

这背后的想法是将两个组字段都封装在逗号之间,以便每个组条目都由逗号封装。因此,与其搜索,不如搜索adm1,adm1,

因此,如果您的列表如下所示:

adm2,adm12,manuel

而且,通过添加逗号,您也可以转换它:

,adm2,adm12,manuel,

您始终可以搜索并找到完美匹配。,adm1,

评论

0赞 sirducas 6/13/2022
嗨,非常感谢,这是正确的,我谢谢你,但我想我找到了一个使用一些逻辑 OR 的解决方案并涵盖一些情况,如下所示: awk -F: '$4 ~ “adm,|adm1$|:adm1,” {print $1}' sup_groups.txt
0赞 kvantour 6/13/2022
@sirducas 在以下情况下,您的解决方案可能仍会失败badm1
0赞 sirducas 6/13/2022
是的,我发现了错误,您的解决方案更好并完成工作,但是您能解释一下“ ”之间的逗号吗?
0赞 kvantour 6/13/2022
@sirducas 我添加了更多信息。
0赞 sirducas 6/13/2022
哦,我可以转换打印输出,所以我知道每个单词都以逗号结尾,是的,这也是一个完美的解决方案,谢谢。
0赞 RARE Kpop Manifesto 6/24/2022 #3

一旦 u 设置了每个任务要求,那么主体就变得勉强只是:FS

    NF = !_ < NF

或者更直接:

  {m,n,g}awk —- --NF

=

{m,g}awk 'NF=!_<NF' OFS= FS=':[^:]*:[^:]*:[^:]*[^[:alpha:]]?adm[0-9]+.*$' 

adm
admins
conda
adm1Group