0

I want to grep a file that stops at the first match, example:

${A57}${A17}${A23}${A20}${A35}${A57}${A33}${A24}${A38}${A38}${A24}${A17}${A57}${A33}${A23}${A38}${A18}${E52}${A28}${A28}${A28}${A25}${A38}${A22}${A50}${A30}${A57}${A37}${A18}${A44}${A15}${A28}${A29}${A29}${A29}${A29}${A14} 

When I use grep -o "${A57}.\*${A29}${A14}" I obtain this output:

${A57}${A17}${A23}${A20}${A35}${A57}${A33}${A24}${A38}${A38}${A24}${A17}${A57}${A33}${A23}${A38}${A18}${E52}${A28}${A28}${A28}${A25}${A38}${A22}${A50}${A30}${A57}${A37}${A18}${A44}${A15}${A28}${A29}${A29}${A29}${A29}${A14} 

Now my question is how can I stop grep with the first match of '${A57}' so that I have this output:

${A57}${A37}${A18}${A44}${A15}${A28}${A29}${A29}${A29}${A29}${A14} 
9
  • 1
    In short, there is no way to restrict .* to not retrieve the longest possible match; that's what * means. Some regular expression tools like grep -P (if you have that) allow for non-greedy matching with .*? Commented May 11, 2023 at 11:24
  • In my opinion, this is not about greedy, but about avoiding a second occurrence of ${A57} in the match. Commented May 11, 2023 at 11:28
  • @trincot It looks to me like they are trying to restrict the scope of .* one way or another. Given that we have to guess what these variables contain, there is really no good way to answer it without speculation. Perhaps the OP will want to edit to clarify what behavior exactly they are looking for, if indeed they don't think that the many answers to the duplicate solve their problem. Commented May 11, 2023 at 11:31
  • That is the right way but when I use the expression -P with ".*?" I obtain a blank output. 'grep --color=always -o -P "${A57}.*?${A29}${A14}"', some ideas? Commented May 11, 2023 at 11:32
  • 1
    @Nemsis always use single quotes unless you NEED double quotes, and always use double quotes unless you NEED no quotes. If you follow those rules you won't have to escape the $s. Commented May 11, 2023 at 12:07

1 Answer 1

3

You're trying to use the wrong tool. Using any sed:

$ sed -n 's/.*\(${A57}.*${A29}${A14}\).*/\1/p' file ${A57}${A37}${A18}${A44}${A15}${A28}${A29}${A29}${A29}${A29}${A14} 

or an awk that supports gensub() such as GNU awk:

$ awk '{print gensub(/.*(\${A57}.*\${A29}\${A14}).*/,"\\1",1)}' file ${A57}${A37}${A18}${A44}${A15}${A28}${A29}${A29}${A29}${A29}${A14} 
Sign up to request clarification or add additional context in comments.

2 Comments

Another question: Can you tell me how can I change this command, that the obtained output replace inside a value or file the text sequence like search and replace?
It's really not clear what your comment is trying to ask, and anyway, please don't pile on new requirements. This is already performing a search and replace; it's easy to add a second sed statement like ;s/foo/bar/ if you want to replace foo with bar in the result. If you need more help, please ask a new question, this time with a proper minimal reproducible example

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.