I would like to change:

inlet
{
    type    patch;
    ...
}
outlet
{
        type  patch;
} 

to

inlet
{
    type    wall;
    ...
}
outlet
{
        type  patch;
} 

As a first attempt to achieve this, I tried to limit the range between inlet and outlet and replace "patch" with wall.

echo "inlet { patch } outlet" | sed "/^\(inlet [^ ]*\) .* \([^ ]*\)$/s//\1 wall \2/"

which gave output :

inlet { wall outlet

The last curly bracket is missing.

echo "inlet {patch} outlet {patch}"| sed "/inlet/,/outlet/{s/patch/wall/}"

gave output :

inlet {wall} outlet {patch}

However, I need to make sure that the "patch" that is replaced by wall shall have a "type" in the same line. It is this part I need to resolve now.

2

There are 2 best solutions below

0
potong On BEST ANSWER

This might work for you (GNU sed):

sed -E '/^inlet$/{n;/^\{$/{:a;N;/^\}$/M!ba;s/^(\s+type\s+)\S+/\1wall;/M}}' file 

Search for line containing inlet only.

Print it and fetch the next line.

If that line contains only {, fetch subsequent lines until one containing only }.

Now substitute a line beginning and separated by white space, two words: the first being type and then replace the second word by wall;.

N.B. The use of the M flag in both regexp and the substitution commands, that bound the regexp by line i.e. the anchors respect the ^ and $ anchors, in a multiline string.

0
Ed Morton On

Using any POSIX awk, if you want to replace any string in that position:

$ awk '
    /^[[:alpha:]]/ { f = ($1 == "inlet") }
    f && ($1 == "type") { sub(/[^[:space:]]+;$/,""); $0=$0 "wall;" }
    { print }
' file
inlet
{
    type    wall;
    ...
}
outlet
{
        type  patch;
}

or if you only want to replace patch specifically then change the 2nd line of the script to:

f && ($1 == "type") && ($2 == "patch;") { sub(/[^[:space:]]+;$/,""); $0=$0 "wall;" }

and if there could be spaces before or after the last ; on the line:

f && ($1 == "type") && ($2 ~ /^patch;?$/) { sub(/[^[:space:]]+[[:space:]]*;[[:space:]]*$/,""); $0=$0 "wall;" }