Why I Love Sed and a Clear/Practical Beginner's Guide to Using It

C

CrazedNerd

Guest
Since using linux, my favorite piece of software I have discovered so far is sed. Sed is a command line utility that stands for "stream editor". It was made based off the text editor named "ed", which is different from notepad, gedit, vim, or emacs. With ed, you create text files line by line instead of opening the file and gradually making changes. Sed is much more powerful, and is normally used for making edits to text files instead of adding content to those files or creating new files.

Sed is useful because you can make large changes to a file with one or a few short commands. In this article, I'm going to discuss the ways that I have used the program for practical uses. I'm not going to discuss most of the possible ways to use it or go into a lot of detail about how it works, but after reading this and testing it out, you will be able to use it to make programming and data formatting tasks a lot easier. You get an even greater amount of benefits from sed by combining it with something like awk or perl. However, I personally just love the simplicity of sed, and I use it on a fairly regular basis for fixing my own mistakes or changing files. You only need to have very basic command line familiarity to understand this article, you just need to know what standard input/output is and how to use basic command line utitilies like cat, grep, and echo. If you don't know what I'm talking about, you can learn these things pretty quickly through your search engine. Many of the examples will contain the commands and their output in the code blocks like this:

echo "Hello world!"
Hello world!

If you find any part of this confusing, then feel free to ask questions. Also, feel free to post your own uses for sed or correct my mistakes.

Introduction

Sed is used like this, and comes installed on almost every linux system:

sed <options> <commands> filename

or...

<non-sed-commands> | sed <options> <commands>

You can either use it on a file, or pipe commands into sed. Piping is the process of taking the output from one command or several and putting that output into sed. Here's an example of each.

The most common way people use sed is with substitution. Let's say you wrote a short story that's in a text file, and the main character's name is John.

However, you later decide that you don't like your name choice, and you want to make the characters Saudi Arabian. With sed, you could change every instance of
"John" to "Abdullah" like this:

sed 's/John/Abdullah/g' story

This simple sed command will look through every line in the file and apply that change to it, then print the whole story to standard output. This way, the file is not changed. I will tell you how to change the file shortly, but it's good practice to only print the text to standard output first so that you can verify that those are the changes you want to make.

However, I realize you may not have a short story on your computer, so we will start by editing two sentences. Copy this text into a basic text file and name it "sample" or anything else, just remember to type that filename instead:

The quick brown fox jumped over the lazy dog.
The dog bit the fox and the fox bit the dog.

Let's say you wanted to change the fox to a cat. Execute this command:

sed 's/cat/fox/' sample

This will output the fallowing text to your terminal:

The quick brown cat jumped over the lazy dog.
The dog bit the cat and the fox bit the dog.

You may notice that on the second line, the change was only applied to the first instance of "fox". That's because substitution (the "s command") by default only changes the first instances of something on a line. If we wanted to change every instance of "cat" to "fox", we would add the "g" flag at the end of it:

sed 's/cat/fox/g' sample

That stands for "global", but of course, if the thing that we want to change only occurs once per line like on a lot of data sheets, then we wouldn't need to add the g flag to the end of the command.

Now, let's talk about the other way to use the sed command. You don't have to use it on files, but you can also use it on standard output like this:

echo "the lazy dog" | sed 's/frisky/SUPER/'
the SUPER dog

cat sample | sed 's/fox/cat/g'
The quick brown cat jumped over the lazy dog.
The dog bit the cat and the cat bit the dog.

The second example does the same thing as using the file as input, but we are piping the file into sed with thecat command. If you want to change the file permanently, then you can use the "-i" option:

sed -i 's/fox/cat/g' sample

However, it might be safer to send the changed version to a different file entirely with redirection:

sed 's/fox/cat/g' sample > new-file

This leaves the file "sample" exactly the way it was before, but sends the changed file to a new file named "new-file".

Meta-characters and regular expressions

Sed is a much more practical and useful program if you use meta-characters. These will enable you to be more specific about what you change in a document, or change a broader selection of characters. When you use meta-characters in this way, they are said to be "regular expressions". A regular expression can also be any matching search pattern used on the command line. This may sound confusing, but they're not very different than when you enter something to look for in a search engine. The search term itself, like "influential albums of the 90s", is like a regular expression, but instead of looking for actual albums, we are looking for the exact text "influential albums of the 90s" within the document. In sed, we are matching the regular expression to what we want to see or change. Here are metacharacters that are read and interpreted by sed to be different from what they are by themselves:

. [ ] ^ $ * \+ \?

These are not the only meta-characters interpreted by sed, but these are the ones you use in regular expressions. For example, let's start with the period. To sed, a period or dot . is not a literal period or dot when you specify text that you want to change. It means any character except for a newline, in sed this is said (hahaha...) to be a "wildcard". Let's refer to our earlier example to demonstrate what this means:

The quick brown cat jumped over the lazy dog.
The dog bit the cat and the cat bit the dog.

sed 's/T../That/g' sample

The above sed command would not change any periods in the sentence, but it changes any capital T fallowed by any two characters. If the T were at the end of the sentence (without a trailing period), then that would not be changed. As it stands, we get this:

That quick brown cat jumped over the lazy dog.
That dog bit the cat and the fox bit the dog.

If we wanted to also change the lower case "the", we could also do that with brackets, which are used to indicate either a selection of characters or a range of characters:

sed 's/[Tt]../That/g' sample

That would change every single "the" (or any instance of a t fallowed by two characters...) into "That". When we use brackets, we are saying "if the expression contains any of these items, make the change". If we used "[The]" as a regular expression, it would not target the word "The", but any occurrence of T,h, or e. We can also use it for ranges:

sed 's/[a-z]/something/g'
sed 's/[0-9]/something/g'

The first one refers to any lower case letter in the alphabet, and the second example refers to any single digit/number. Even though using meta-characters this way allows us to refer to a very broad range of things in our text, they also create a conundrum: what if we just wanted to change a period (or dot) without it referring to any character like it does by default? What if we wanted to change our brackets to parenthesis? We can do that with a backslash. We are "escaping" the character:

echo "What is your name." | sed 's/\./?/'
What is your name?

If you think that looks confusing, then you can also separate the parts of the command with other characters, sed allows for most other characters on your keyboard to replace the slashes, including spaces:

echo "What is your name." | sed 's \. ? '
What is your name?

The substitute command is broken into 3 or 4 parts: the "s", to tell sed to subsitute, the text you want to replace in every line, the text you want to replace it with, and lastly (which we don't use in the command above) the space for flags like "g". If we don't escape the period/dot, then we get this:

echo "What is your name." | sed 's . ? '
?hat is your name.

That's because the "." was matched with the first thing it found, and like sed normally does without the g flag at the end of it, it only makes the change to the first occurrence. With the g flag, this is what we would get:

echo "What is your name." | sed 's . ? g'
??????????????????

Isn't that fun? Sed replaced every single character, including spaces, with a question mark.

We can also use regular expressions to match anything that a line begins or ends with, using the caret ^ and the dollar sign $.

Let's say we entered the wrong month for a list of dates, but don't want to change the day on those lines that have the proper month:

04/02/2023
02/05/2023
02/07/2023

If we entered the command 's/02/04/', then we would unfortunately change the day from 04/02/2023 as well, but we can avoid doing that with our caret:

sed 's/^02/04/' sample
04/02/2023
04/05/2023
04/07/2023

If we wanted to replace a period at the end of a sentence with a question mark, but not interfere with periods in the middle of a sentence, then we could do it like this with the dollar sign $:

Hello, my name is Sam. What is your name.
I really like jazz. What is your favorite style of music.

sed 's \.$ ? ' sample
Hello, my name is Sam. What is your name?
I really like jazz. What is your favorite style of music?

As a reminder, I'm replacing the slashes with spaces in that example just to make the command syntax look neater. When you get comfortable with using sed, you will not be bothered by having backslashes and slashes within the same command. The last set of metacharacters that are used in regular expressions are the asterisk, plus sign, and question mark. These all are used to find numbers of occurrences for a preceding character:

* \+ \?

Notice that the asterisk * is interpreted as a meta by default, but with the plus sign and question mark, you need to escape them so they are used as regular expressions because sed interprets them literally by default. One particularly common way that people use the asterisk is with the single wildcard:

.*

This means "zero or more of any number of any characters" to sed. This is particularly useful to match a range of characters within a line:

The quick brown fox jumped over the lazy dog.

Let's say i wanted the fox to do something else:

sed 's/jumped.*/drank purple lemonade./' sample
The quick brown fox drank purple lemonade.

In this example, everything starting with "jumped" is being replaced, because ".*" means all characters that come after "jumped". While * is used to match zero or more occurences of something, \+ is used to match one or more occurrences of something, while \? is used to match zero or one occurrence of something. Here's how they compare:

sed 's/T*/B/g' sample
BhBeB BqBuBiBcBkB BbBrBoBwBnB BfBoBxB BjBuBmBpBeBdB BoBvBeBrB BtBhBeB BlBaBzByB BdBoBgB.B

sed 's/T\+/B/g' sample
Bhe quick brown fox jumped over the lazy dog.

sed 's/T\?/B/g' sample
BhBeB BqBuBiBcBkB BbBrBoBwBnB BfBoBxB BjBuBmBpBeBdB BoBvBeBrB BtBhBeB BlBaBzByB BdBoBgB.B

With the asterisk and question mark, sed went and inserted a "B" between every part of the sentence, even when there was nothing, because there don't need to be any matches for them to match. However, with \+, there has to be at least one match. It would seem that question mark and asterisk do exactly the same thing since they produced the same result here, but \? produces a larger number of matches when the matches are situated right next to each other:

echo "seed" | sed 's/e*/B/g'
BsBdB

echo "seed" | sed 's/e\?/B/g'
BsBBdB

Since * matches "zero or more occurrences" of the letter e, then two e's together in "seed" only match once, but with /?, sed looks at the two e's separately, and replaces it with a "B" twice instead of once.

Here's a practical example that i've taken from a couple other sources: this command removes HTML tages from a document using the meta characters i've discussed:

sed 's/<[^>]*>//g' file

In this example, we are using the caret and asterisk to tell sed to match tags even if there are any number of other > enclosed within them, which is necessary since in any HTML document, there are going to be tags within tags. Also, since the aterisk matches zero or more times, everything else inside of the tags will be removed, like "BODY", "HTML", etc. Since these are wrapped within <>, then this will effectively remove all HTML tags from a document, leaving only the body of text.

Why you should normally wrap your commands in single quotes

If we are editing something without meta-characters or spaces, then we don't need to use double quotes. In the example I gave earlier of replacing a name in a short story, this will work just fine:

sed s/John/Abdullah/g story

However, you can seriously screw up your files if you aren't careful with sed, and if you use the -i option, then you can't ever undo your edits. Sed and the terminal interpret metacharacters in different ways, the single quotes ensure that the terminal only sees your characters literally while sed interprets them the way it's meant to. Also, wrapping your sed commands with quotes allows you to manipulate blank spaces, which a linux terminal would reject:

echo "Hi Sam" | sed s/ / there /
sed: -e expression #1, char 2: unterminated `s' command
echo "Hi Sam" | sed 's/ / there /'
Hi there Sam

Since sed looks at white-space as like it does any letter, number, or punctuation, that makes it far more more powerful and useful. If it looked at white-space as a collapsible separator of words like bash does, then it wouldn't be able very helpful at all for editing text.

Print pattern space

Whenever you make edits to sed, the lines are loaded into pattern space. Pattern space is a buffer, buffers are spaces set aside for memory within software. They are basically a type of virtual RAM. When you execute a command like s/something/something-else/, then the first line of the file or input is loaded into pattern space, then sed makes the edits to pattern space, then prints them to standard output, erases what it put into the pattern space, and starts the process on the second line until each line has been processed. By default, sed prints everything that enters pattern space, so if you use the p command, then everything is printed twice:

echo "Hello world" | sed p
Hello world
Hello world

When editing files, this would probably just be annoying. To stop sed from printing pattern space by default, and just print the pattern space once with this command, we must use the -n. This option suppresses sed's natural tendency to print pattern space:

echo "Hello world" | sed -n p
Hello world

When using the p command on entire files, we can use it to print lines that have a specific line number or contain certain text:

sed -n 1p sample
The quick brown fox jumped over the lazy dog.

sed -n '/Pink/p' sample
Pink flamingos.

Each of those lines are currently contained in my "sample" file, but the first one just prints the first line, and the second one just prints any line containing the regular expression "Pink". In the second example, sed is used in the exact same way that the command utility "grep" is.

If you have some command line experience, you may now be thinking: "So what's the point of using sed this way if you can print an entire file with cat? All you have to do is type cat filename, and the whole document will be printed. Also, if you want to find lines with a regular expression, it's faster to use grep, you can just type grep text-pattern filename, and you will see every line that has the regular expression or text pattern."

And yes, if you just wanted to look at a document, or just print lines that match a regular expressions, then it would be simpler and more practical just to
use cat or grep for those purposes. However, with sed, you can easily print sections of a document somewhere in the middle of the text with addressing:

sed -n '/yes/,/:/p' sed-guide
And yes, if you just wanted to look at a document, or just print lines that match a regular expressions, then it would be simpler and more practical just to use cat or grep for those purposes. However, with sed, you can easily print sections of a document somewhere in the middle of the text with addressing:

Anytime we use commas in a sed command, we are telling sed to act upon a specific range. I often find that I want to see only a specific section of a document,
and sed is great for that. In the above example, sed finds a lines with "yes" then prints all of the text starting there, down to the next line that has a
colon. Sometimes, I make notes on subject matters and put them in text files. I tend to separate sections with all caps titles. To exclusively check out notes
i've made for grep in my "bash-help" document, this is what I do:

Code:
sed -n '/GREP/,/[A-Z][A-Z]/p' bash-help
GREP

stands for "global regular expression print"...

This section is 33 lines long, so i'm only going to show you this part, but what I am telling sed to do is print starting at "GREP" in caps, then stop at the next section, which is the next line with capital letters from A-Z. We can also use sed this way to print ranges of lines using numbers:

sed -n 20,50p some-file

This will print lines numbered 20 through 50, but nothing else. The p command also has other uses when we use multiple commands together. Execute multiple commands in order Sed actually gives us many different ways to do this: the -e option, grouping with curly braces{}, the semicolon;, and scripting. I'm only going to talk about the semicolon and scripting. Let's say you wanted to make several changes to text in a document with the s command, but you only want sed to print the lines that you changed. You could do it like this:

sed -n 's/flamingos/Elephants/;/Elephants/p' sample
Pink Elephants.

Here, I've suppressed sed's natural tendency to print every line of the file, changed the text, then told sed to only print the changed text. You can do this with any number of commands, and with sed you can execute the changes on any number of files. I like using the semicolon better this way because there is less typing.

With the -f option, you can also turn sed into an interpreter of scripts. This way, you can just list commands on each line in a separate file, and unlike when you use sed from the command line, you do not use single quotes or you'll get an error. If you wanted to, you could make a separate file named "elephants.sed" (the .sed extension is just there for organization purposes, sed can read any text file) and put this inside of it:

s/flamingos/Elephants/
/Elephants/p

Then, if you feed that file to sed, it will do the exact same thing as the above example, given that you have have "Pink flamingos." in your text file:

sed -n -f elephants.sed sample

We are giving sed two arguments: the argument after "-f" is the script, and then we are putting a text file for editing at the end of the command like normal.

Each command in the script acts on every line of the file in sequence, when command 1 applies it's effects to every line, then command 2 applies its own changes to the text that has already been effected by command 1. Even though this is not a practical script, you only would want to create a sed script if you want to execute certain commands on a text regularly.

Delete lines

We have already discussed how to delete text from a line in examples, just substitute the text text you want to delete with absolutely nothing:

sed 's/text//' file

However, sed also has a command for deleting lines of a specific number or containing specific text. It works the same way as the print command:

sed 20d file

sed '/^#/d'

The first example only erases the 20th line from a file, but the second erases every line from a file beginning with "#". In UNIX related programming languages (bash, sed, awk, and others), that is a way to remove comments from a file very easily. I have done it myself when posting scripts online to make it shorter to read. If you wanted to ONLY retain the comments, then you do it like this:

sed '/^#/!d' file

That exclamation point is used to exclude your changes from the lines you are refferring to. Here are a couple more practical ways to use the deletion command.
This will delete blank spaces by referring to lines that begin and end with nothing:

sed /'^$/d' file

And here's how you can remove leading spaces from every line in a file:

sed 's/^[ \t]*//g' file

Back referencing

What if you want to edit part of a text, but leave other parts of it the way they are? That is the purpose of back referencing, and it's one of the best features of sed. In the most basic form of back referencing, we refer to the entire text in a substitution command with an ampersand &. This works in an opposite manner from the other metacharacters you use in a regular expression: Rather than only acting on the text you are matching,the ampersand only acts on the text you substitute:

echo "Hello" | sed 's/Hello/"&"/'
"Hello"

The ampersand, used this way, is basically a back-reference to the entire regular expression you entered previously. It's used to just add something to your text. With numeric back referencing, you can be more specific about which parts of a text you take and which one you change. I'm going to use | here to delimit the parts of the command because we are going to use both backslashes and spaces:

echo "One Two Three" | sed 's|\(...\) \(...\) \(...\)|\1, \2, \3|'
One, Two, Three

The parenthesis are escaped in order to be used this way, just like \+ and \?. Otherwise, sed will just look for parenthesis in your text. Every time we escape parenthesis with regular expressions inside them, we are creating a group for back referencing: the first group are any three characters fallowed by a space, the second group is the second occurrence, third group the third. They are always numbered from left to right. Then, we use the back references to separate each spelled out number and add commas.

I think that the "icode" tags are a really useful way to make computer text stand out on any forum that regularly discusses programming. However, i hate typing those tags out. So, for this article, i've surrounded a lot of things that i want to surround with those tags with <> so that i could replace it with those tags later using sed:

Code:
sed 's/<\(.*\)>/[icode]\1[\/icode]/' sed-guide > final-draft

That saves me a lot of typing, and allows me to easily make references inside of paragraphs instead of only on separate lines. I'm using the escaped parenthesis to refer to any text inside of tags, then I'm surrounding the group of text with bbc tags instead.

Conclusion

There is a lot to sed that we didn't cover in this guide: there's branches and labels that allow for the creation of loops, hold space, word-boundaries, references to specific numbers of occurrences, more ways of addressing, and even more. However, in this guide I have covered all the different aspects of sed that I actually use when editing text files. If you want to learn more, the best book I have found on the subject is "Sed and Awk: 101 Hacks" by Ramesh Natarajan. After reading this guide, you will find that book to be pretty easy to read and understand. There are times when to use sed, and times when the changes are so small
and specific that it's better just to use your text editor. For example, if you misspell a single word while you are typing, it's better to just correct the error, using a long sed command just for that would be very silly and time consuming. It's meant just to make large changes to a text file really quickly, it doesn't work on word processor documents. It works find on .csv files though, because those are just text files with comma separated values.

Sed also has a lot of practical value to keep you from having to open your text editor, yet one needs to be very careful about what they type. I've found that redirection tends to be better than using the -i option. If you are a programmer, and you get really comfortable with using sed, then you can make your work much less of a hassle.

Note: I've also found that writing guides with text files isn't as easy as i thought it was. I'd definetly do the whole icode thing differently if I did this again just because of the way that nano justifies text, yet the important thing is that the examples here are illustrative.

EDITS: Along with the missing single quotes in the part where we delete everything except the comments in a file like osprey pointed out, I also made a mistake in the part where I talk about editing the month in a list of dates with the caret, which has now been fixed.
 
Last edited by a moderator:


Crazy, this is really very, very good :)

I know what you mean about the formatting, and I will go in and clean it up for you.

I hope your creative Muse inspires you to write more, in your own time, of course.

Chris
 
Crazy, this is really very, very good :)

I know what you mean about the formatting, and I will go in and clean it up for you.

I hope your creative Muse inspires you to write more, in your own time, of course.

Chris
Thanks, i recently have gotten more of an urge to write. I'm glad that you thought it was clear and well written, I enjoyed writing it.
 
Thanks CrazedNerd for all that work. Great read and appreciated.

On my debian system there was one difference which I show here below ... the ! needs to be escaped to get the intended outcome if the command options are not quoted. Your example doesn't use quotes. Without quotes, if the ! is not escaped, there is another message as shown below, but when quotes are applied there is no need to escape the ! and the outcome is correct:

Code:
[flipn@flop ~]$ cat file12
masked
masked
the quick brown fox jumps over the lazy dog
masked
masked

[flip@flop ~]$ sed /^m/!d file12
sed /^m/deborphan file12
sed: -e expression #1, char 6: extra characters after command

[flip@flop ~]$ sed /^m/\!d file12
masked
masked
masked
masked

[flip@flop ~]$ sed '/^m/!d' file12
masked
masked
masked
masked

This may be to do with debian since "deborphan" is a debian term, but I haven't met this with sed before.
 
Last edited:
Thanks CrazedNerd for all that work. Great read and appreciated.

On my debian system there was one difference which I show here below ... the ! needs to be escaped to get the intended outcome if the command options are not quoted. Your example doesn't use quotes. Without quotes, if the ! is not escaped, there is another message as shown below, but when quotes are applied there is no need to escape the ! and the outcome is correct:

Code:
[flipn@flop ~]$ cat file12
masked
masked
the quick brown fox jumps over the lazy dog
masked
masked

[flip@flop ~]$ sed /^m/!d file12
sed /^m/deborphan file12
sed: -e expression #1, char 6: extra characters after command

[flip@flop ~]$ sed /^m/\!d file12
masked
masked
masked
masked

[flip@flop ~]$ sed '/^m/!d' file12
masked
masked
masked
masked

This may be to do with debian since "deborphan" is a debian term, but I haven't met this with sed before.
Yeah that was probably the only thing i didn't test, i'll check it out later
 
Thanks CrazedNerd for all that work. Great read and appreciated.

On my debian system there was one difference which I show here below ... the ! needs to be escaped to get the intended outcome if the command options are not quoted. Your example doesn't use quotes. Without quotes, if the ! is not escaped, there is another message as shown below, but when quotes are applied there is no need to escape the ! and the outcome is correct:

Code:
[flipn@flop ~]$ cat file12
masked
masked
the quick brown fox jumps over the lazy dog
masked
masked

[flip@flop ~]$ sed /^m/!d file12
sed /^m/deborphan file12
sed: -e expression #1, char 6: extra characters after command

[flip@flop ~]$ sed /^m/\!d file12
masked
masked
masked
masked

[flip@flop ~]$ sed '/^m/!d' file12
masked
masked
masked
masked

This may be to do with debian since "deborphan" is a debian term, but I haven't met this with sed before.
Yeah, nice find...it's better to always use quotes, and test things without writing them to a file first. I got the same results with my larget bash script, i use Ubuntu:
Code:
xarathustra@xarathustra:~$ sed '/^#/!d' compare.sh
#!/bin/bash
#easier to read format for showing differences between files
#instructions in how to use script
#instructions for script, ensures that proper argument is included
#error if either file doesn't exist, specific
#assigns lines from file to arrays
#if $1 contains "-u", then print unique lines
#if $1 contains "-c", then compare side by side
#if line contains "-s", then display lines that are the same when compared side by side
#remove files used to create arrays earlier

xarathustra@xarathustra:~$ sed /^#/!d compare.sh
sed /^#/date +%s compare.sh
sed: -e expression #1, char 6: extra characters after command
 
I still want to spend some time on sed, I did spend some time on it a long time ago but not enough for me to understand it enough to use without having to look something up or just too Google how someone else used sed to solve something I was trying to do. Thanks for sharing! What resources did you use the get the hang of sed better yourself?
 
I still want to spend some time on sed, I did spend some time on it a long time ago but not enough for me to understand it enough to use without having something up or just too Google how someone else used sed to solve something I was trying to do. Thanks for sharing! What resources did you use the get the hang of sed better yourself?
It mostly was just a combination of practice and that book i mentioned in the end...i was even able to use sed and awk to make my normal job easier.
 
It mostly was just a combination of practice and that book i mentioned in the end...i was even able to use sed and awk to make my normal job easier.
lol have only read part of your original post so I hadn't gotten to that part yet, I will read the full part later. Thanks!
 
LOL He learned by posting a dozen topics/questions on Linux.org!

I watched 'em. Well, I skimmed 'em. I might have even commented in one or two, but I'm far from a sed guru. Once upon a time, I was fairly fluent in RegEx. I'd toss that into the mix of things to learn when diving down this rabbit hole.
 
LOL He learned by posting a dozen topics/questions on Linux.org!

I watched 'em. Well, I skimmed 'em. I might have even commented in one or two, but I'm far from a sed guru. Once upon a time, I was fairly fluent in RegEx. I'd toss that into the mix of things to learn when diving down this rabbit hole.
Yeah that's true as well, i was pretty confused about the matching with * at first, but with thread i posted and practice it eventually was clear.
 
I'm in the process of fixing all the other mistakes in the article, the most egregious one i found so far was the example of how to remove HTML tags. It's now been cleaned up, if before it didn't make any sense to you.
 

Members online


Top