简体   繁体   中英

Using sed with regex to replace text on OSX and Linux

I am trying to replace some strings inside a file with sed using Regular Expressions. To complicate the matter, this is being done inside a Makefile script that needs to work on both osx and linux .

Specifically, within file.tex I want to replace

\subimport{chapters/}{xxx}

with

\subimport{chapters/}{xxx-yyy}

( xxx and yyy are just example text.)

Note, xxx could contain any letters, numbers, and _ (underscore) but really the regex can simply match anything inside the brackets. Sometimes there is some whitespace at the beginning of the line before \\subimport... .

The design of the string being searched for requires a lot of escaping (when searched for with regex) and I am guessing somewhere therein lies my error.

Here's what I've tried so far:

sed -i'.bak' -e 's/\\subimport\{chapters\/\}\{xxx\}/\\subimport\{chapters\/\}\{xxx-yyy\}/g' file.tex
# the -i'.bak' is required so SED works on OSX and Linux
rm -f file.tex.bak # because of this, we have to delete the .bak files after

This results in an error of RE error: invalid repetition count(s) when I build my Makefile that contains this script.

I thought part of my problem was that the -E option for sed was not available in the osx version of sed . It turns out, when using the -E option, fewer things should be escaped (see comments on my question).

POSIX-ly:

sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#'
  • # is used as the parameter separator for sed 's s (Substitution)

  • \\(\\\\subimport{chapters/}{[[:alnum:]_]\\+\\) is the captured group, containing everything required upto last } , preceeded by one or more alphabetics, digits, and underscore

  • In the replacement, the first captured group is followed by the required string, closed by a }

Example:

$ sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#' <<<'\subimport{chapters/}{foobar9}'
\subimport{chapters/}{foobar9-yyy}

$ sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#' <<<'\subimport{chapters/}{spamegg923}'
\subimport{chapters/}{spamegg923-yyy}

Here's is the version that ended up working for me.

sed -i.bak -E 's#^([[:blank:]]*\\subimport{chapters/}{[[:alnum:]_]+)}$#\1-yyy}#' file.tex
rm -f file.tex.bak

Much thanks go to @heemayl. Their answer is the better written one, it simply required some tweaking to get a version that worked for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM