ИМХО, это гораздо проще / чище сделать в Perl, Python и т. Д.
Но если вам нужно использовать sed, вот отправная точка:
$ sed -ne ':START
/alias/b ALIASES
p
b
:ALIASES
p
n
/alias/b ALIASES
i \
alias foo=bar
:REST
p
n
b REST
' < aliases > aliases.new
$ diff -u aliases aliases.new
--- aliases 2011-04-07 08:30:30.000000000 +1000
+++ aliases.new 2011-04-07 08:34:09.000000000 +1000
@@ -3,6 +3,7 @@
alias a=apple
alias b=banana
+alias foo=bar
echo something else
$ mv aliases.new aliases
Более полная версия, котораяработает для меня это
$ name=b
$ replacement=barney
sed -i.bak -n -e '
:START
/^[[:space:]]*alias/ b NEXTALIAS
# not an alias, print it as-is and go to next line
p
b
:NEXTALIAS
# start processing this alias line
/^[[:space:]]*alias[[:space:]][[:space:]]*'"$name"'/ b REPLACE
/^[[:space:]]*alias/ b PRINT
# found the end of the alias block, insert the alias here
:INSERT
# grab the indentation back from the hold space
x
s/$/alias '"$name='$replacement'"'/
p
x
b REST
:PRINT
# remember how the last alias line was indented...
h
s/^\([[:space:]]*\).*/\1/
x
# ... and print the line
p
n
b NEXTALIAS
:REPLACE
# we found an existing alias with a matching name, replace it
# I add single quotes around replacement so that the caller can write
# replacement='echo something' rather than replacement="'echo something'"
s/\(.*\)alias[[:space:]][[:space:]]*'"$name"'.*/\1alias '"$name='$replacement'"/'
b REST
:REST
# we made it past the aliases block, just print the remaining lines
p
n
b REST
' aliases
$ diff -u aliases.bak aliases
--- aliases.bak 2011-04-07 09:09:26.000000000 +1000
+++ aliases 2011-04-07 09:11:05.000000000 +1000
@@ -2,7 +2,7 @@
echo blah
alias a=apple
-alias b=banana
+alias b='barney'
alias c=carrot
echo something else
Обратите внимание, что есть некоторые крайние случаи, которые я не обработал явно.Например, что должно произойти, если есть два блока псевдонимов?Что, если в середине блока псевдонимов есть закомментированный псевдоним и т. Д.