简体   繁体   中英

A grep (or sed, or awk) command to select all lines that follow a specific pattern after a specific start line in a file

In the yml files of Docker Compose , the volumes are declared in a section that starts with volumes: line and followed by patterns such as - host/dir:guest:dir . The sesction ends with the start of the next section, which its name would not be the same all the time, and it could be any of ports: , environment: , and networks: , among others. There is usually more than one volumes: section, and the number of lines in each of those is not known (and is not constant across the volumes: sections).

I need to extract all the volume declarations (ie, - host/dir:guest:dir ) from all volumes: sections of a yml file.

Thanks!

An example yml file:

version: '2'
services:
  service1:
    image: repo1/image1
    volumes:
      - /dir1/dir2:/dir3/dir4
      - /dir5/dir6:/dir7/dir8
    ports:
      - "80:80"
  service2:
    image: repo2/image2
    volumes:
      - /dir9/dir10:/dir11/dir12
    environment:
      - A: B

awk one-liner

Assuming you have / in each volume declaration

Input :

version: '2'
services:
  service1:
    image: repo1/image1
    volumes:
      - /dir1/dir2:/dir3/dir4
      - /dir5/dir6:/dir7/dir8
    ports:
      - "80:80"
  service2:
    image: repo2/image2
    volumes:
      - /dir9/dir10:/dir11/dir12
    environment:
      - A: B
    volumes:
      - /dir1/dir2:/dir3/dir4
      - /dir5/dir6:/dir7/dir8
meow:

Output :

$awk '$0!~"/"{a=0}  /volumes:/{a=1; next}a' file
      - /dir1/dir2:/dir3/dir4
      - /dir5/dir6:/dir7/dir8
      - /dir9/dir10:/dir11/dir12
      - /dir1/dir2:/dir3/dir4
      - /dir5/dir6:/dir7/dir8

$0!~"/"{a=0} : If the record/line doesn't contain / that means it's not a volume declaration ; set a=0
/volumes:/{a=1; next} /volumes:/{a=1; next} : If the line contains volumes: then set a=1 and next ie jump to next record
a : To print the records if a=1

PS : If in your yml file a tag containing / can come just after volumes then this can fail. If that's the case then use this awk :

$awk '$1!~"-"{a=0}  /volumes:/{a=1; next}a' file

This will reset a if first field isn't -

awk '$1=="-"{if (f) print; next} {f=/^[[:space:]]*volumes:/}' file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM