• Uncategorized

About regex : Sed-failed-to-match-non-whitespace-characters-with-character-class

Question Detail

I want to extract filter rules configured in /etc/lvm/lvm.conf, like filter = [ "r|/dev/sda|" ]. I want sed to return "r|/dev/sda|". So I have tried the following script:

echo ' filter = [ "r|/dev/sda|" ] ' | sed -r 's:^\s*filter\s*=\s*\[\s*([^\s]+)\s*\]:\1:g'

But it didn’t work, the script has returned filter = [ "r|/dev/sda|" ].
I’ve tried a few on line regex tester, the group has been matched correctly.

However, if I replace [^\s]+ by .+, it works.

Doesn’t [^\s]+ mean more than one non whitespace characters ?

Any idea please?

Question Answer

Acc. to regular-expressions.info:

One key syntactic difference is that the backslash is NOT a metacharacter in a POSIX bracket expression. So in POSIX, the regular expression [\d] matches a \ or a d.

So you need to replace [^\s] with [^[:space:]] (any char other than whitespace).

Example:

echo ' filter = [ "r|/dev/sda|" ] ' | sed -E 's:^\s*filter\s*=\s*\[\s*([^[:space:]]+)\s*\]:\1:g'

Output: "r|/dev/sda|"

Alternatively easier and shorter than [^[:space:]] you can do with \S+ without using brackets []

\S means non whitespace char

echo ' filter = [ "r|/dev/sda|" ] ' | sed -r 's:^\s*filter\s*=\s*\[\s*(\S+)\s*\]:\1:g'

https://ideone.com/PxDX1Q

In case grep solution is acceptable :

grep -oP 'filter.*\K".*?"' inputfile

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.