1

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?

2 Answers 2

3

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

awk '/^#/ {gsub("#", "", $0); txt=$0} {gsub("Linux", txt, $0); print}' file.txt
Sign up to request clarification or add additional context in comments.

1 Comment

I want to do this in the context of an apache mod_sed directive, there's no performant way that I'm aware of to run apache output through awk.
2

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

1 Comment

Interesting, I had thought that without the -n switch it was resulting in an extra newline at the beginning of the output, but I just tested it again the output looked correct. Just edited my answer to remove it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.