grep between pattern and exclude start/end pattern in output

Viewed 83

I have file.txt from which I need to grep first occurrence of a pattern. How can I grep and get matched string only ':whitespace' and 'end of line' I m trying below command

cat file.txt |  grep -m1 -P "(:\s+).*ccas-apache$"

But it gives me

name: nginx-ccas-apache

and I want is

nginx-ccas-apache

file.txt

pod: nginx-ccas-apache-0
        name: nginx-ccas-apache
        image: myregnapq//ccas_apache
        name: nginx-filebeat
pod: nginx-ccas-apache-1
        name: nginx-ccas-apache
        image: myregnapq/ccas_apache
        name: nginx-filebeat
5 Answers

Another approach using sed:

sed -En '/^[[:space:]]+name:[[:space:]](.*ccas-apache)$/{s//\1/p;q}' file.txt

Explanation

  • -En Use extended regexp with -E and prevent the default printing of a line by sed with -n

  • /^[[:space:]]+name:[[:space:]](.*ccas-apache)$/ The pattern that specifies what to match

  • If the previous pattern matched, run commands between the curly brackets

  • s//\1/p Use the last matched pattern with // and replace with group 1. Then print the pattern space with p

  • q exit sed

The regex matches:

  • ^ Start of string
  • [[:space:]]+name:[[:space:]] Match name: with leading spaces and single space after
  • (.*ccas-apache) Capture group 1, match optional chars and ccas-apache
  • $ End of string

Output

nginx-ccas-apache

Note that you don't have to use cat

See an online demo.

Using grep

$ grep -Pom1 'name: \K.*$' file.txt
nginx-ccas-apache

You can use awk, too:

awk -F: '/:[[:space:]].*ccas-apache$/{sub(/^[[:space:]]+/, "", $2); print $2; exit}'  file

Details:

  • -F: - a colon is used as a field separator
  • :[[:space:]].*ccas-apache$ - searches for a line with :, a whitespace, then any text, ccas-apache at the end of the string, and once found
  • sub(/^[[:space:]]+/, "", $2) - remove the initial whitespaces from Field 2
  • print $2 - then print the Field 2 value
  • exit - stop processing the file.

See the online demo:

#!/bin/bash
s='pod: nginx-ccas-apache-0
        name: nginx-ccas-apache
        image: myregnapq//ccas_apache
        name: nginx-filebeat
pod: nginx-ccas-apache-1
        name: nginx-ccas-apache
        image: myregnapq/ccas_apache
        name: nginx-filebeat'

awk -F: '/:[[:space:]].*ccas-apache$/{sub(/^[[:space:]]+/, "", $2); print $2; exit}' <<< "$s"

Output: nginx-ccas-apache

INPUT

pod: nginx-ccas-apache-0
        name: nginx-ccas-apache
        image: myregnapq//ccas_apache
        name: nginx-filebeat
pod: nginx-ccas-apache-1
        name: nginx-ccas-apache
        image: myregnapq/ccas_apache
        name: nginx-filebeat

CODE

  • enter any properly-escaped pattern for __ that includes the string tail $

    • 3 ways of saying the same thing
    • any one solution works in gawk, mawk-1, mawk-2, or macos nawk
mawk '_{exit} _=$(NF=NF)~__' FS='^.*[ \t]' __='ccas-apache$' OFS=
or
gawk '_{exit} NF*=_=$(NF)~__' FS='^.*[ \t]' __='ccas-apache$' OFS=
or
nawk '_{exit} _=NF*=$NF~__' FS='^.*[ \t]' __='ccas-apache$' OFS=

OUTPUT

nginx-ccas-apache

GENERIC SOLUTION

  • not just at the tail
  • this time enter pattern at FS

CODE

{m,g}awk '_{exit} _=(!_<NF)*sub("[^ \t]*"(FS)"[^ \t]*","\4&\4")*\
                    gsub("^[^\4]*\4|\4[^\4]*$","")' FS='your_pattern_here'

OUTPUT

FS='image' 

    >>> `image:`

FS='myregnapq'

    >>> `myregnapq//ccas_apache`

With your shown samples please try following awk code.

awk -F':[[:space:]]+' '
$1~/^[[:space:]]+name$/ && $2~/^[^-]*-ccas-apache$/{
  print $2
  exit
}
' Input_file

Explanation: Simple explanation would be, setting field separator as colon followed by space(1 or more occurrences). In main program checking condition if first field matches regex starts with space followed by name AND 2nd field matches regex ^[^-]*-ccas-apache$ then printing 2nd field of that line and `exit from program.

Related