Andrew Hancox
Andrew Hancox

Reputation: 2340

Use Sed to replace a string with another string obtained from a regex

I want to replace a string (in the example the word Linux) with whatever is between the #'s on the first line.

So I want to turn:

#Windows#
1. Linux Sysadmin, Linux Scripting etc.
2. Databases - Oracle, mySQL etc.
3. Security (Firewall, Network, Online Security etc)
4. Storage in Linux
5. Productivity (Too many technologies to explore, not much time available)

into:

1. Windows Sysadmin, Windows Scripting etc.
2. Databases - Oracle, mySQL etc.
3. Security (Firewall, Network, Online Security etc)
4. Storage in Windows
5. Productivity (Too many technologies to explore, not much time available)

or

#Solaris#
1. Linux Sysadmin, Linux Scripting etc.
2. Databases - Oracle, mySQL etc.
3. Security (Firewall, Network, Online Security etc)
4. Storage in Linux
5. Productivity (Too many technologies to explore, not much time available)

into:

1. Solaris Sysadmin, Solaris Scripting etc.
2. Databases - Oracle, mySQL etc.
3. Security (Firewall, Network, Online Security etc)
4. Storage in Solaris
5. Productivity (Too many technologies to explore, not much time available)

Just using sed. I've got as far as: sed ' /^#[a-zA-Z ]*/{ h d } /Linux/ G'

I think what I need to do is is run a regular expression using the hold buffer as the replacement pattern which I guess would look like s/Linux/g but I can't find a way to do this. Anyone got any ideas?

Upvotes: 1

Views: 1319

Answers (2)

Andrew Clark
Andrew Clark

Reputation: 208475

Here is an sed solution:

sed '
/^#.*#$/{                      # if replacement text is matchd
s/#//g                           # remove all pound chars
h                                # copy pattern space to hold space
d                                # delete pattern space and start over
}                              # end if
:a                             # create label "a"
G                              # append hold to pattern
s/Linux\(.*\)\n\(.*\)/\2\1/    # replace Linux with contents of hold space
ta                             # if above replacement succeeded, go to "a"
s/\n.*//                       # remove replacement text and print pattern space
' file.txt

One-liner if you can use ; to separate commands:

sed '/^#.*#$/{s/#//g;h;d};:a;G;s/Linux\(.*\)\n\(.*\)/\2\1/;ta;s/\n.*//' file.txt

Upvotes: 2

anubhava
anubhava

Reputation: 785196

You will be better off using awk. Consider this script:

awk '/^#/ {gsub("#", "", $0); txt=$0} {gsub("Linux", txt, $0); print}' file.txt

Upvotes: 3

Related Questions