Mandatory Surgeon General warning: you shouldn't use regex to parse HTML.
In this very limited case, you might use
(<[^>]*class\s*=\s*"[^"]*)\bhk\b([^"]*")
and replace it with \1whatever\2
. Then "hk" becomes "whatever" provided it's inside a class inside a HTML tag. The \b specifier will prevent "ohka" from matching and the \s ensures that "class = " and "class=" will be treated the same. You will need a multiline modifier for the case of
<p class
="ab hk cd" style="display: block">
You can experiment using https://regex101.com .
Update (clarification):
(<[^>]*class\s*=\s*"[^"]*)\bhk\b([^"]*")
will, indeed, find <body class="ab hk cd" style="x">
and match and replace the sequence <body class="ab hk cd"
. Note, in the regex, that the first part - the one before "hk" - is parenthesized, and so is the part after.
The "trick" is in the replacement formula, where I specified "\1whatever\2" (in some libraries it could be $1whatever$2, or ${1}whatever${2}, or {$1}whatever{$2} and so on). The meaning is that the content of the first parenthesized group goes into \1, and so on.
So the three groups will be:
'<body class="ab ' captured by '(<[^>]*class\s*=\s*"[^"]*)' into $1
'hk' captured by "\bhk\b" and discarded
cd" captured by '([^"]*")' into $2
and the replacement \1whatever\2
will become
\1 whatever \2
'<body class="ab ' whatever 'cd"'
which is the desired output. The replacement of the first and third groups with themselves feels needless and wasteful, but I know no other means of doing this - regex replacement requires regenerating the whole match, and the "extra" parts are required to correctly frame the match itself.
(You could use this kind of syntax to swap two strings around a pivot, for example).