Pergunta

I want to replace a single line in a file with multiple lines, e.g., I want to replace a particular function call, say,

foo(1,2)

with

if (a > 1) {  
    foo(1,2)  
} else {  
    bar(1,2)  
}

How can I do it in bash?

Foi útil?

Solução

This is what the sed s command was built for:

shopt -s extglob

ORIG="foo(1,2)"
REP="if (a > 1) {  
      foo(1,2)  
} else {  
      bar(1,2)  
}"

REP="${REP//+(
)/\\n}"

sed "s/$ORIG/$REP/g" inputfile > outputfile

Note that the REP="${REP//\+( )/\\n}" lines are only needed if you want to define the REP in the formatted way that I did on line two. It might be simpler if you just used \n and \t in REP to begin with.

Edit: Note! You need to escape ' and \ as well in your REP if you have them.

Edit in response to the OP's question

To change your original file without creating a new file, use sed's --in-place flag, like so:

sed --in-place "s/$ORIG/$REP/g" inputfile

Please be careful with the --in-place flag. Make backups before you run it because all changes will be permanent.

Outras dicas

This might work for you:

cat <<\! |
> a
> foo(1,2)
> b
> foo(1,2)
> c
> !
> sed '/foo(1,2)/c\
> if (a > 1) {\
>     foo(1,2)\
> } else {\
>     bar(1,2)\
> }' 
a
if (a > 1) {
    foo(1,2)
} else {
    bar(1,2)
}
b
if (a > 1) {
    foo(1,2)
} else {
    bar(1,2)
}
c

To replace strings in-place in a file, you can use ed (as conveniently tagged in the question). Assuming your input file looks like this:

line before
foo(1,2)
line between
    foo(1,2)
line after

You can write a script to do the substitution and store it in a file such as script.ed:

%s/\([[:blank:]]*\)foo(1,2)/\1if (a > 1) {\
\1    foo(1,2)\
\1} else {\
\1    bar(1,2)\
\1}/
w
q

Notice that this takes indentation into account; every line is prepended with whatever blanks were there before the function call in the original file, so the result would look like this:

$ ed -s infile < script.ed
$ cat infile
line before
if (a > 1) {
    foo(1,2)
} else {
    bar(1,2)
}
line between
    if (a > 1) {
        foo(1,2)
    } else {
        bar(1,2)
    }
line after

Should the function call not be on a line on its own but potentially prepended by other characters that shouldn't be removed, you could use this as the first line of the substitution:

%s/\([[:blank:]]*\)\(.*\)foo(1,2)/\1\2if (a > 1) {\

So this

    } something; foo(1,2)

would become

    } something; if (a > 1) {
        foo(1,2)
    } else {
        bar(1,2)
    }

with indentation still properly accounted for.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top