1

I have a file where I basically need grep to return the "key" associated with a particular value.

For instance, if I have:

[abc]
field1=34234
field2=t2342

[def]
field1=44354
field2=23423

I want to be able to grep, say, 23423, and then basically match on [def] and return/print out the contents of the brackets (e.g. def).

The file is formatted something like this, where I want to match the first line containing [ and ] before the argument to grep, if that makes sense.

I found this question, which is similar, where -B 1 will give you the line before, and some variant of that can be used to prevent some number of lines before the match.

The problem is I can't count on the exact number of lines between the match and the first line with brackets before it, so I want to avoid doing that and simply match for the first line containing a bracket before.

Is this possible to do with grep, or a similar bash utility?

InterLinked
  • 1,247
  • 2
  • 18
  • 50
  • 1
    `awk -v RS= '/23423/{gsub(/[][]/, "", $1); print $1}' file`? – Wiktor Stribiżew Nov 27 '19 at 23:12
  • 1
    This is easy to do with `awk`. If the line matches the section heading format, assign it to a variable. If the line matches the search string, print the variable. – Barmar Nov 27 '19 at 23:12
  • @WiktorStribiżew If you're going to give the answer, post it as a real answer, not a comment. But we prefer not to write code for them. – Barmar Nov 27 '19 at 23:12
  • That looks like an INI file. This might be useful: [How to parse and convert ini file into bash array variables? - Server Fault](https://serverfault.com/q/345665/403609) – wjandrea Nov 27 '19 at 23:34
  • @wjandrea It's not an ini, it's a .conf file, but I'll look into these suggestions – InterLinked Nov 27 '19 at 23:47
  • @InterLinked From what I understand, .conf files can be in the INI format – wjandrea Nov 28 '19 at 01:21

1 Answers1

2

I suggest reading the paragraphs one by one and once a paragraph contains a searched value get the first field without [ and ]:

awk -v RS= '/23423/{gsub(/[][]/, "", $1); print $1}' file

Note that [][] matches [ or ].

Or, get the first field with trimmed out [ and ]:

awk -v RS= '/23423/{print substr($1, 2, length($1)-2)}' file

See the online awk demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • This works from the shell, but not when I call it from an external application. To exact errors are `[Nov 27 19:15:52] WARNING[3105][C-00002091]: pbx_variables.c:721 pbx_substitute_variables_helper_full: Error in extension logic (missing '}') [Nov 27 19:15:52] WARNING[3105][C-00002091]: pbx_functions.c:462 func_args: Can't find trailing parenthesis for function 'SHELL(awk -v RS= '/text/{gsub(/[][]/, "", $1'?` I'm saving the SHELL output to a variable, so can I get rid of the $1 somehow and maybe simplify the expression? Removing print didn't fix it – InterLinked Nov 28 '19 at 00:17
  • You can't get rid of anything here, you need to adapt if for your app. Sometimes, doubling `$` helps, i.e. `$$1` (makefile usage). Not sure if one GNU `grep` will help, `grep -Poz -m1 '\[\K[^][]+(?=](?:\R.+)*23423)' file`, see [demo](https://ideone.com/iaVaIF). – Wiktor Stribiżew Nov 28 '19 at 00:41
  • I tried that in the shell and it doesn't work, not sure what the demo is doing – InterLinked Nov 28 '19 at 00:44
  • So, you are not using GNU grep then. – Wiktor Stribiżew Nov 28 '19 at 00:44
  • How would the awk work in a batch script? The input, 23423, is $1 (an argument), so that conflicts with the $1 in the awk statement – InterLinked Nov 28 '19 at 00:59
  • @InterLinked There is no conflict, the `$1` is inside single quotes. – Wiktor Stribiżew Nov 28 '19 at 01:39
  • There is a conflict, but I figured it out, it works in an external shell scritp – InterLinked Nov 28 '19 at 01:45
  • @InterLinked You could have added that detail to the question, it would be even more helpful. – Wiktor Stribiżew Nov 28 '19 at 08:12