Given the following partial file:
[epel]
name=Extra Packages for Enterprise Linux 8 - $basearch
# It is much more secure to use the metalink, but if you wish to use a local mirror
# place its address here.
#baseurl=https://download.example/pub/epel/8/Everything/$basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-8&arch=$basearch&infra=$infra&content=$contentdir
disable_repo=zabbix
enabled=1
gpgcheck=1
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
[epel-debuginfo]
name=Extra Packages for Enterprise Linux 8 - $basearch - Debug
# It is much more secure to use the metalink, but if you wish to use a local mirror
# place its address here.
#baseurl=https://download.example/pub/epel/8/Everything/$basearch/debug
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-8&arch=$basearch&infra=$infra&content=$contentdir
enabled=0
disable_repo=test
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
gpgcheck=1
I am trying to extract the disable_repo
line found within the [epel]
block of code so I extract a value of “zabbix”. I can find the right block of text using [epel]((?s)(?:(?!nn).)*)
but am having problems getting it closer than that.
2
You can use a negative lookahead assertion to ensure that every character between [epel]
and a matching disable_repo=...
is not the beginning of another [...]
block header, and capture what comes after disable_repo=
in a group:
[epel]$(?:(?![[^]]*]).)*^disable_repo=([^n]*)
Demo: https://regex101.com/r/QmQdYg/3
Note that the single line mode has to be enabled for .
to match any character, including a newline, and the multi-line mode has to be enabled for ^
and $
to match the start and the end of a line rather than the string.
If the format of the file has that structure, you can prevent crossing blocks or matching disable_repo=
from the start of the string.
Then match disable_repo=
and capture the value in group 1.
^[epel](?:n(?!disable_repo=|[[^][n]*]$).*)*ndisable_repo=(.*)
The pattern matches:
^
Start of string[epel]
Match[epel]
(?:
Non capture group to repeat as a whole partn
Match a newline(?!
Negative lookaheaddisable_repo=
Match literally|
Or[[^][n]*]$
Match[...]
till the end of the string
)
Close the lookahead.*
Match the whole line
)*
ndisable_repo=(.*)
Match a newline,disable_repo=
and capture the value in group 1
See a regex demo
If your values have no empty lines in between, you can prevent some backtracking when there is no match by not allowing empty lines adding [^Sn]*$
as a third alternative.
^[epel](?:n(?!disable_repo=|[[^][n]*]$|[^Sn]*$).*)*ndisable_repo=(.*)