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.
0I 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