How Sed Can Be Used to Replace Multiple Patterns Within a String for Different Patterns

I want to replace multiple numbers in a line for different values. For example, in the string "uncertainty = { 0.01 , 0.01 }" it should substitute for string "uncertainty = { 0.2 , 0.2 }"

The problem is that these lines appear in hundreds of files with different quantities of numbers inside the brackets.

It could be:

"uncertainty = {  0.1 , 0.1, 0.1 }"

for

"uncertainty = {  0.3 , 0.3, 0.3 }"

or

"uncertainty = {  0.1 , 0.1, 0.1 , 0.1, 0.1, 0.1}"

for

"uncertainty = {  0.3 , 0.3, 0.3 , 0.3, 0.3, 0.3}

and so on, and I have to substitute all of them.

I could not see how sed could be used to do that.

2 Answers

Use regular expressions. Convert one item inside the curly brackets into a regular expression such as:

[0-9]\.[0-9]1

What this expression means is "a number, a period, a number, a one". If the format is consistent through-and-through, this will only replace instances of "0.01" when put through sed.

There are other tools that would meet these needs as well, such as awk and tr, but you would still use regular expressions for them as well. To replace numbers such as this in bulk, you could replace that "1" with another [0-9] or a [1-3] to specify numbers in the range of 1-3.

For more info on Regular Expressions see Rexegg. They greatly expand the usefulness of virtually all text manipulation utilities.

0

I read about awk and it turned out to help half of my questions: to go through substrings of a string that matches a given string. Because awk have some limitations, I used sed to clean up the mess, like this in which v1 and v2 are passed via a shell script that call this code

The awk part:

{
    found = match($0,"uncertainty")
    i = 4
    if (found) {
    while ( i < NF){
        if ($i = v1) {
          $i = v2
        }
        i = i + 2
    }
    print "        " $0 
    }
    else
    {
    print $0
    }
}

The shell part:

#!/bin/bash

# Check if directory already exists,

#!/bin/bash

# Check if directory already exists,

bitSizeDir="$1"
value1="$2"
value2="$3"

_mydir="$(pwd)"
find $bitSizeDir/ -type f  > Files;
while read line; do
    folder=`dirname "$line"`
    file=`basename "$line"`
    if [ "$file" = "input.c" ] ; then
    awk -v v1=$value1 -v v2=$value2 -f changeValues.awk $line > input.new
    mv input.new $folder
    cd $folder
    rm $file
    mv input.new input.c
    sed -i '' "s/$3 , \}/ \} /g" input.c
        cd $_mydir
    fi
done < Files
rm Files

Your Answer

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

Elena Rostova

Elena Rostova

Lead Health, Wellness & Medical Journalist

Elena Rostova holds a Master's degree in Public Health Journalism. She covers groundbreaking medical research, holistic wellness trends, mental health awareness, and nutritional science.

Share this article
Twitter Facebook Pinterest