I have a file called test similar to the following:

<h6>test morning</h6>

I know I would use:

sed -i -- 's/name//g' test

To remove name from the file, but how do I remove <h6>test morning</h6>?

The string could be anywhere in the file and the file could be anything like a .css or .html file.


For such cases you can use any character instead /. For example

sed -i 's|<h6>test morning</h6>||g' test

For string mach patterns you should escape first one

sed -i '\|<h6>test morning</h6>|s///g' test

If you have few / in the pattern may be easy to escape it directly

sed -i '/<h6>test morning<\/h6>/s///g' test
  • What do you mean 'for string match patterns'? Jul 8 '16 at 14:42
  • @Proletariat I mean pattern which used for string addressing (see example 2nd and 3rd above. FYR such variant should be quicker a little for large text)
    – Costas
    Jul 8 '16 at 15:04

Perl to the rescue!

In Perl, you can use a variable in the pattern part, and you can use quotemeta (or the corresponding \Q escape) to escape special characters:

REPLACE='<h6>test morning</h6>' perl -pe 's/\Q$ENV{REPLACE}//'

with Perl you can apply the same change for file & dir paths as well ... this code snippet turned into a bash function has been the mostly used part of code during the last 5 years both for professional and free-time projects ...

        # some initial checks the users should set the vars in their shells !!!
        test -z $dir_to_morph && exit 1 "You must export dir_to_morph=<<the-dir>> - it is empty !!!"
        test -d $dir_to_morph || exit 1 "The dir to morph : \"$dir_to_morph\" is not a dir !!!"
        test -z $to_srch && exit 1 "You must export to_srch=<<str-to-search-for>> - it is empty !!!"
        test -z $to_repl && exit 1 "You must export to_repl=<<str-to-replace-with>> - it is empty !!!"

        echo "INFO dir_to_morph: $dir_to_morph"
        echo "INFO to_srch:\"$to_srch\" " ;
        echo "INFO to_repl:\"$to_repl\" " ;
        sleep 2

        echo "INFO START :: search and replace in non-binary files"
        #search and replace ONLY in the txt files and omit the binary files
        while read -r file ; do (
           #debug echo doing find and replace in $file
           echo "DEBUG working on file: $file"
           echo "DEBUG searching for $to_srch , replacing with :: $to_repl"

           # we do not want to mess with out .git dir
           # or how-to check that a string contains another string
           case "$file" in
           perl -pi -e "s#\Q$to_srch\E#$to_repl#g" "$file"
        done < <(find $dir_to_morph -type f -not -exec file {} \; | grep text | cut -d: -f1)

        echo "INFO STOP  :: search and replace in non-binary files"

        #search and repl %var_id% with var_id_val in deploy_tmp_dir
        echo "INFO search and replace in dir and file paths dir_to_morph:$dir_to_morph"

        # rename the dirs according to the pattern
        while read -r dir ; do (
           perl -nle '$o=$_;s#'"\Q$to_srch\E"'#'"$to_repl"'#g;$n=$_;`mkdir -p $n` ;'
        done < <(find $dir_to_morph -type d|grep -v '.git')

        # rename the files according to the pattern
        while read -r file ; do (
           perl -nle '$o=$_;s#'"\Q$to_srch\E"'#'"$to_repl"'#g;$n=$_;rename($o,$n) unless -e $n ;'
        done < <(find $dir_to_morph -type f -not -path "*/node_modules/*" |grep -v '.git'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.