This is what expand is for, e.g. expand -t 4 file.txt.
expand won't edit the original file, but you can redirect to a new file and mv it over the original, or use sponge if you have it installed, e.g.
expand -t 4 file.txt > file.new && mv file.new file.txt
or
expand -t 4 file.txt | sponge file.txt
FYI, see unexpand to do the reverse, convert multiple spaces to tabs.
Both expand and unexpand support using fixed-width tabs (e.g. -t 4 or -t 8, etc) or a list of tab positions (e.g. -t 4,12,32). They also have options to only convert initial, leading spaces/tabs. See the man pages for details.
For more info about sponge, see man sponge and Is there a standard alternative to sponge to pipe a file into itself?. In short, it does the redirect and mv for you, using a temporary file. BTW, never try to redirect stdout to the same file that's currently being used as stdin. The shell will overwrite it before it even gets read.
sponge is from the moreutils package.
PS: See also GNU indent or one of many other similar source-code reformatting tools.
-roption, which enables extended regular expressions: that means you need to use+not\+for the quantifier. This code looks for one leading tab followed by a plus character. – glenn jackman Jun 05 '21 at 13:16