在文件列表中找到两个字符串并获取文件名

时间:2018-03-09 16:00:40

标签: bash awk grep

我有以下文件:

100005.txt  107984.txt  116095.txt  124152.txt  133339.txt  139345.txt  18147.txt  25750.txt  32647.txt  40390.txt  48979.txt  56502.txt  64234.txt  72964.txt  80311.txt  888.txt    95969.txt
100176.txt  108084.txt  116194.txt  124321.txt  133435.txt  139438.txt  18331.txt  25940.txt  32726.txt  40489.txt  49080.txt  56506.txt  64323.txt  73063.txt  80481.txt  88958.txt  9601.txt
100347.txt  108255.txt  116378.txt  124494.txt  133531.txt  139976.txt  18420.txt  26034.txt  32814.txt  40589.txt  49082.txt  56596.txt  64414.txt  73163.txt  80580.txt  89128.txt  96058.txt
100447.txt  108343.txt  116467.txt  124594.txt  133627.txt  140519.txt  18509.txt  26128.txt  32903.txt  40854.txt  49254.txt  56768.txt  64418.txt  73498.txt  80616.txt  89228.txt  96148.txt
100617.txt  108432.txt  11647.txt   124766.txt  133728.txt  14053.txt   1866.txt   26227.txt  32993.txt  41026.txt  49308.txt  56857.txt  6449.txt   73670.txt  80704.txt  89400.txt  96239.txt
10071.txt   108521.txt  116556.txt  124854.txt  133830.txt  141062.txt  18770.txt  26327.txt  33093.txt  41197.txt  49387.txt  57029.txt  64508.txt  7377.txt   80791.txt  89500.txt  96335.txt
100788.txt  10897.txt   116746.txt  124943.txt  133866.txt  141630.txt  18960.txt  2646.txt   33194.txt  41296.txt  4971.txt   57128.txt  64680.txt  73841.txt  80880.txt  89504.txt  96436.txt

部分文件如下:

spec: 
  annotations: 
    name: "ubuntu4"
    labels: 
      key: "cont_name"
      value: "ubuntuContainer4"

    labels: 
      key: "cont_service"
      value: "UbuntuService4"


  task: 
    container: 
      image: "ubuntu:latest"
      args: "tail"
      args: "-f"
      args: "/dev/null"
      mounts: 
        source: "/home/testVolume"
        target: "/opt"
      replicated: 
        replicas: 1 

我想获取包含 ubuntu AND 副本的每个文件名。

我试过awk '/ubuntu/ && /replicas/{print FILENAME}' *.txt,但它似乎对我不起作用。

有关如何解决此问题的任何想法?

4 个答案:

答案 0 :(得分:4)

Grep可以返回与字符串匹配的文件列表。您可以嵌套该grep调用,以便首先获得与 ubuntu 匹配的文件列表,然后使用该文件列表获取与副本匹配的文件列表。 / p>

grep -l replicas $( grep -l ubuntu *.txt )

这假设至少有一个文件与ubuntu匹配。要绕过该限制,您可以先为一个文件的存在添加测试,然后进行组合搜索:

grep -q ubuntu *.txt && grep -l replicas $( grep -l ubuntu *.txt )

答案 1 :(得分:2)

通过对每个字符串使用计数器检查两个字符串是否出现在给定文件中,然后检查它们是否递增。您可以使用GNU awk上提供的BEGINFILE执行此操作:

awk 'BEGINFILE {ub=0; re=0}
     /ubuntu/ {ub++}
     /replicas/ {re++}
     (ub>0 && re>0) {print FILENAME; nextfile}' *.txt

当它开始读取文件时,它将两个计数器设置为0:一个用于一个字符串,另一个用于另一个字符串。当找到其中一个模式时,它会增加其相应的计数器。然后它继续检查两个计数器是否已增加。如果是这样,它将使用包含该字符串的FILENAME变量打印其文件名。此外,它使用nextfile跳过文件的其余部分,因为无需继续检查模式。

答案 2 :(得分:2)

awk '/ubuntu/ && /replicas/{print FILENAME}' *.txt

在同一行查找两个正则表达式。要在同一个文件中找到它们,但可能在与GNU awk for ENDFILE的单独行中找到它们:

awk '/ubuntu/{u=1} /replicas/{r=1} ENDFILE{if (u && r) print FILENAME; u=r=0}' *.txt

或更有效地添加gawks nextfile构造并优先切换到BEGINFILE(如@fedorqui已经显示)而不是ENDFILE,因为文件读取之间的所有内容都是设置2个变量:

awk 'BEGINFILE{u=r=0} /ubuntu/{u=1} /replicas/{r=1} u && r{print FILENAME; nextfile}' *.txt

其他问题就是:

awk '
    FNR==1{prt()} /ubuntu/{u=1} /replicas/{r=1} END{prt()}
    function prt() {if (u && r) print fname; fname=FILENAME; u=r=0}
' *.txt

答案 3 :(得分:1)

如果没有访问过子目录:

for f in *.txt 
do  
   grep -q -m1 'ubuntu' $f && grep -q -m1 'replicas' $f && echo "found: $f" 
done

或作为oneliner:

for f in *.txt ; do  grep -q -m1 'ubuntu' $f && grep -q -m1 replicas $f && echo found:$f ; done

-q使得grep安静,因此匹配不显示,-m1只搜索1个匹配,因此grep可以快速报告匹配。

&&是短路的,所以如果第一个grep找不到任何东西,那么第二个就不会尝试。

对于在管道中进一步处理文件,你当然会消除发现的"发现:"。