3965 lines
164 KiB
Plaintext
3965 lines
164 KiB
Plaintext
|
|
Archive-Name: editor-faq/sed
|
|
Posting-Frequency: irregular
|
|
Last-modified: 10 March 2003
|
|
Version: 015
|
|
URL: http://sed.sourceforge.net/sedfaq.html
|
|
Maintainer: Eric Pement (pemente@northpark.edu)
|
|
|
|
THE SED FAQ
|
|
|
|
Frequently Asked Questions about
|
|
sed, the stream editor
|
|
|
|
CONTENTS
|
|
|
|
1. GENERAL INFORMATION
|
|
1.1. Introduction - How this FAQ is organized
|
|
1.2. Latest version of the sed FAQ
|
|
1.3. FAQ revision information
|
|
1.4. How do I add a question/answer to the sed FAQ?
|
|
1.5. FAQ abbreviations
|
|
1.6. Credits and acknowledgements
|
|
1.7. Standard disclaimers
|
|
|
|
2. BASIC SED
|
|
2.1. What is sed?
|
|
2.2. What versions of sed are there, and where can I get them?
|
|
|
|
2.2.1. Free versions
|
|
|
|
2.2.1.1. Unix platforms
|
|
2.2.1.2. OS/2
|
|
2.2.1.3. Microsoft Windows (Win3x, Win9x, WinNT, Win2K)
|
|
2.2.1.4. MS-DOS
|
|
2.2.1.5. CP/M
|
|
2.2.1.6. Macintosh v8 or v9
|
|
|
|
2.2.2. Shareware and Commercial versions
|
|
|
|
2.2.2.1. Unix platforms
|
|
2.2.2.2. OS/2
|
|
2.2.2.3. Windows 95/98, Windows NT, Windows 2000
|
|
2.2.2.4. MS-DOS
|
|
|
|
2.3. Where can I learn to use sed?
|
|
|
|
2.3.1. Books
|
|
2.3.2. Mailing list
|
|
2.3.3. Tutorials, electronic text
|
|
2.3.4. General web and ftp sites
|
|
|
|
3. TECHNICAL
|
|
3.1. More detailed explanation of basic sed
|
|
3.1.1. Regular expressions on the left side of "s///"
|
|
3.1.2. Escape characters on the right side of "s///"
|
|
3.1.3. Substitution switches
|
|
3.2. Common one-line sed scripts. How do I . . . ?
|
|
|
|
- double/triple-space a file?
|
|
- convert DOS/Unix newlines?
|
|
- delete leading/trailing spaces?
|
|
- do substitutions on all/certain lines?
|
|
- delete consecutive blank lines?
|
|
- delete blank lines at the top/end of the file?
|
|
|
|
3.3. Addressing and address ranges
|
|
3.4. Address ranges in GNU sed and HHsed
|
|
3.5. Debugging sed scripts
|
|
3.6. Notes about s2p, the sed-to-perl translator
|
|
3.7. GNU/POSIX extensions to regular expressions
|
|
|
|
4. EXAMPLES
|
|
ONE-CHARACTER QUESTIONS
|
|
4.1. How do I insert a newline into the RHS of a substitution?
|
|
4.2. How do I represent control-codes or non-printable characters?
|
|
4.3. How do I convert files with toggle characters, like +this+,
|
|
to look like [i]this[/i]?
|
|
|
|
CHANGING STRINGS
|
|
4.10. How do I perform a case-insensitive search?
|
|
4.11. How do I match only the first occurrence of a pattern?
|
|
4.12. How do I parse a comma-delimited (CSV) data file?
|
|
4.13. How do I handle fixed-length, columnar data?
|
|
4.14. How do I commify a string of numbers?
|
|
4.15. How do I prevent regex expansion on substitutions?
|
|
4.16. How do I convert a string to all lowercase or capital letters?
|
|
|
|
CHANGING BLOCKS (consecutive lines)
|
|
4.20. How do I change only one section of a file?
|
|
4.21. How do I delete or change a block of text if the block contains
|
|
a certain regular expression?
|
|
4.22. How do I locate a paragraph of text if the paragraph contains a
|
|
certain regular expression?
|
|
4.23. How do I match a block of specific consecutive lines?
|
|
4.23.1. Try to use a "/range/, /expression/"
|
|
4.23.2. Try to use a "multi-line\nexpression"
|
|
4.23.3. Try to use a block of "literal strings"
|
|
4.24. How do I address all the lines between RE1 and RE2, excluding the lines themselves?
|
|
4.25. How do I join two lines if line #1 ends in a [certain string]?
|
|
4.26. How do I join two lines if line #2 begins in a [certain string]?
|
|
4.27. How do I change all paragraphs to long lines?
|
|
|
|
SHELL AND ENVIRONMENT
|
|
4.30. How do I read environment variables with sed ...
|
|
4.31.1. ... on Unix platforms?
|
|
4.31.2. ... on MS-DOS or 4DOS platforms?
|
|
4.32. How do I export or pass variables back into the environment ...
|
|
4.32.1. ... on Unix platforms?
|
|
4.32.2. ... on MS-DOS or 4DOS platforms?
|
|
4.33. How do I handle shell quoting in sed?
|
|
|
|
FILES, DIRECTORIES, AND PATHS
|
|
4.40. How do I read (insert/add) a file at the top of a textfile?
|
|
4.41. How do I make substitutions in every file in a directory, or
|
|
in a complete directory tree?
|
|
4.41.1. ... ssed solution
|
|
4.41.2. ... Unix solution
|
|
4.41.3. ... DOS solution
|
|
4.42. How do I replace "/some/UNIX/path" in a substitution?
|
|
4.43. How do I replace "C:\SOME\DOS\PATH" in a substitution?
|
|
4.44. How do I emulate file-includes, using sed?
|
|
|
|
5. WHY ISN'T THIS WORKING?
|
|
5.1. Why don't my variables like $var get expanded in my sed script?
|
|
5.2. I'm using 'p' to print, but I have duplicate lines sometimes.
|
|
5.3. Why does my DOS version of sed process a file part-way through
|
|
and then quit?
|
|
5.4. My RE isn't matching/deleting what I want it to. (Or, "Greedy vs.
|
|
stingy pattern matching")
|
|
5.5. What is CSDPMI*B.ZIP and why do I need it?
|
|
5.6. Where are the man pages for GNU sed?
|
|
5.7. How do I tell what version of sed I am using?
|
|
5.8. Does sed issue an exit code?
|
|
5.9. The 'r' command isn't inserting the file into the text.
|
|
5.10. Why can't I match or delete a newline using the \n escape
|
|
sequence? Why can't I match 2 or more lines using \n?
|
|
5.11. My script aborts with an error message, "event not found".
|
|
|
|
6. OTHER ISSUES
|
|
6.1. I have a problem that stumps me. Where can I get help?
|
|
6.2. How does sed compare with awk, perl, and other utilities?
|
|
6.3. When should I use sed?
|
|
6.4. When should I NOT use sed?
|
|
6.5. When should I ignore sed and use Awk or Perl instead?
|
|
6.6. Known limitations among sed versions
|
|
6.7. Known incompatibilities between sed versions
|
|
|
|
6.7.1. Issuing commands from the command line
|
|
6.7.2. Using comments (prefixed by the '#' sign)
|
|
6.7.3. Special syntax in REs
|
|
6.7.4. Word boundaries
|
|
6.7.5. Commands which operate differently
|
|
|
|
7. KNOWN BUGS AMONG SED VERSIONS
|
|
7.1. ssed v3.59
|
|
7.2. GNU sed v4.0 - v4.0.5
|
|
7.3. GNU sed v3.02.80
|
|
7.4. GNU sed v3.02
|
|
7.5. GNU sed v2.05
|
|
7.6. GNU sed v1.18
|
|
7.7. GNU sed v1.03
|
|
7.8. sed v1.6 (Briscoe)
|
|
7.9. sed v1.5 (Helman)
|
|
7.10. sedmod v1.0 (Chen)
|
|
7.11. HP-UX sed
|
|
7.12. SunOS sed v4.1
|
|
7.13. SunOS sed v5.6
|
|
7.14. Ultrix sed v4.3
|
|
7.15. Digital Unix sed
|
|
|
|
|
|
------------------------------
|
|
|
|
1. GENERAL INFORMATION
|
|
|
|
1.1. Introduction - How this FAQ is organized
|
|
|
|
This FAQ is organized to answer common (and some uncommon)
|
|
questions about sed, quickly. If you see a term or abbreviation in
|
|
the examples that seems unclear, see if the term is defined in
|
|
section 1.5. If not, send your comment to pemente[at]northpark.edu.
|
|
|
|
1.2. Latest version of the sed FAQ
|
|
|
|
The newest version of the sed FAQ is usually here:
|
|
|
|
http://sed.sourceforge.net/sedfaq.html (HTML version)
|
|
http://sed.sourceforge.net/sedfaq.txt (plain text)
|
|
http://www.student.northpark.edu/pemente/sed/sedfaq.html
|
|
http://www.student.northpark.edu/pemente/sed/sedfaq.txt
|
|
http://www.faqs.org/faqs/editor-faq/sed
|
|
ftp://rtfm.mit.edu/pub/faqs/editor-faq/sed
|
|
|
|
Another FAQ file on sed by a different author can be found here:
|
|
|
|
http://www.dreamwvr.com/sed-info/sed-faq.html
|
|
|
|
1.3. FAQ revision information
|
|
|
|
In the plaintext version, changes are shown by a vertical bar (|)
|
|
placed in column 78 of the affected lines. To remove the vertical
|
|
bars (use double quotes for MS-DOS):
|
|
|
|
sed 's/ *|$//' sedfaq.txt > sedfaq2.txt
|
|
|
|
In the HTML version, vertical bars do not appear. New or altered
|
|
portions of the FAQ are indicated by printing in dark blue type.
|
|
|
|
In the text version, words needing emphasis may be surrounded by
|
|
the underscore '_' or the asterisk '*'. In the HTML version, these
|
|
are changed to italics and boldface, respectively.
|
|
|
|
1.4. How do I add a question/answer to the sed FAQ?
|
|
|
|
Word your question briefly and send it to pemente[at]northpark.edu,
|
|
indicating your proposed change. We'll post it on the sed-users
|
|
mailing list (see section 2.3.2) and discuss it there. If it's
|
|
good, your contribution will be added to the next edition.
|
|
|
|
1.5. FAQ abbreviations
|
|
|
|
files = one or more filenames, separated by whitespace
|
|
gsed = GNU sed
|
|
ssed = super-sed
|
|
RE = Regular Expressions supported by sed
|
|
LHS = the left-hand side ("find" part) of "s/find/repl/" command
|
|
RHS = the right-hand side ("replace" part) of "s/find/repl/" cmd
|
|
nn+ = version _nn_ or higher (e.g., "15+" = version 1.5 and above)
|
|
|
|
files: "files" stands for one or more filenames entered on the
|
|
command line. The names may include any wildcards your shell
|
|
understands (such as ``zork*'' or ``Aug[4-9].let''). Sed will
|
|
process each filename passed to it by the shell.
|
|
|
|
RE: For details on regular expressions, see section 3.1.1., below.
|
|
|
|
1.6. Credits and acknowledgements
|
|
|
|
Many of the ideas for this FAQ were taken from the Awk FAQ:
|
|
http://www.faqs.org/faqs/computer-lang/awk/faq/
|
|
ftp://rtfm.mit.edu/pub/usenet/comp.lang.awk/faq
|
|
|
|
and from the old Perl FAQ:
|
|
http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/index.html
|
|
|
|
The following individuals have contributed significantly to this
|
|
document, and have provided input and wording suggestions for
|
|
questions, answers, and script examples. Credit goes to these
|
|
contributors (in alphabetical order by last name):
|
|
|
|
Al Aab, Yiorgos Adamopoulos, Paolo Bonzini, Walter Briscoe, Jim
|
|
Dennis, Carlos Duarte, Otavio Exel, Sven Guckes, Aurelio Jargas,
|
|
Mark Katz, Toby Kelsey, Eric Pement, Greg Pfeiffer, Ken Pizzini,
|
|
Niall Smart, Simon Taylor, Peter Tillier, Greg Ubben, Laurent
|
|
Vogel.
|
|
|
|
1.7. Standard disclaimers
|
|
|
|
While a serious attempt has been made to ensure the accuracy of the
|
|
information presented herein, the contributors and maintainers of
|
|
this document do not claim the absence of errors and make no
|
|
warranties on the information provided. If you notice any mistakes,
|
|
please let us know so we can fix it.
|
|
|
|
------------------------------
|
|
|
|
2. BASIC SED
|
|
|
|
2.1. What is sed?
|
|
|
|
"sed" stands for Stream EDitor. Sed is a non-interactive editor,
|
|
written by the late Lee E. McMahon in 1973 or 1974. A brief history
|
|
of sed's origins may be found in an early history of the Unix
|
|
tools, at <http://www.columbia.edu/~rh120/ch106.x09>.
|
|
|
|
Instead of altering a file interactively by moving the cursor on
|
|
the screen (as with a word processor), the user sends a script of
|
|
editing instructions to sed, plus the name of the file to edit (or
|
|
the text to be edited may come as output from a pipe). In this
|
|
sense, sed works like a filter -- deleting, inserting and changing
|
|
characters, words, and lines of text. Its range of activity goes
|
|
from small, simple changes to very complex ones.
|
|
|
|
Sed reads its input from stdin (Unix shorthand for "standard
|
|
input," i.e., the console) or from files (or both), and sends the
|
|
results to stdout ("standard output," normally the console or
|
|
screen). Most people use sed first for its substitution features.
|
|
Sed is often used as a find-and-replace tool.
|
|
|
|
sed 's/Glenn/Harold/g' oldfile >newfile
|
|
|
|
will replace every occurrence of "Glenn" with the word "Harold",
|
|
wherever it occurs in the file. The "find" portion is a regular
|
|
expression ("RE"), which can be a simple word or may contain
|
|
special characters to allow greater flexibility (for example, to
|
|
prevent "Glenn" from also matching "Glennon").
|
|
|
|
My very first use of sed was to add 8 spaces to the left side of a
|
|
file, so when I printed it, the printing wouldn't begin at the
|
|
absolute left edge of a piece of paper.
|
|
|
|
sed 's/^/ /' myfile >newfile # my first sed script
|
|
sed 's/^/ /' myfile | lp # my next sed script
|
|
|
|
Then I learned that sed could display only one paragraph of a file,
|
|
beginning at the phrase "and where it came" and ending at the
|
|
phrase "for all people". My script looked like this:
|
|
|
|
sed -n '/and where it came/,/for all people/p' myfile
|
|
|
|
Sed's normal behavior is to print (i.e., display or show on screen)
|
|
the entire file, including the parts that haven't been altered,
|
|
unless you use the -n switch. The "-n" stands for "no output". This
|
|
switch is almost always used in conjunction with a 'p' command
|
|
somewhere, which says to print only the sections of the file that
|
|
have been specified. The -n switch with the 'p' command allow for
|
|
parts of a file to be printed (i.e., sent to the console).
|
|
|
|
Next, I found that sed could show me only (say) lines 12-18 of a
|
|
file and not show me the rest. This was very handy when I needed to
|
|
review only part of a long file and I didn't want to alter it.
|
|
|
|
# the 'p' stands for print
|
|
sed -n 12,18p myfile
|
|
|
|
Likewise, sed could show me everything else BUT those particular
|
|
lines, without physically changing the file on the disk:
|
|
|
|
# the 'd' stands for delete
|
|
sed 12,18d myfile
|
|
|
|
Sed could also double-space my single-spaced file when it came time
|
|
to print it:
|
|
|
|
sed G myfile >newfile
|
|
|
|
If you have many editing commands (for deleting, adding,
|
|
substituting, etc.) which might take up several lines, those
|
|
commands can be put into a separate file and all of the commands in
|
|
the file applied to file being edited:
|
|
|
|
# 'script.sed' is the file of commands
|
|
# 'myfile' is the file being changed
|
|
sed -f script.sed myfile # 'script.sed' is the file of commands
|
|
|
|
It is not our intention to convert this FAQ file into a full-blown
|
|
sed tutorial (for good tutorials, see section 2.3). Rather, we hope
|
|
this gives the complete novice a few ideas of how sed can be used.
|
|
|
|
2.2. What versions of sed are there, and where can I get them?
|
|
|
|
2.2.1. Free versions
|
|
|
|
Note: "Free" does not mean "public domain" nor does it necessarily
|
|
mean you will never be charged for it. All versions of sed in this
|
|
section except the CP/M versions are based on the GNU general
|
|
public license and are "free software" by that standard (for
|
|
details, see http://www.gnu.org/philosophy/free-sw.html). This
|
|
means you can get the source code and develop it further.
|
|
|
|
At the URLs listed in this category, sed binaries or source code
|
|
can be downloaded and used without fees or license payments.
|
|
|
|
2.2.1.1. Unix platforms
|
|
|
|
ssed v3.60
|
|
ssed is the version recommended by the FAQ maintainers, since it
|
|
shares the same codebase with GNU sed, has the most options, and is
|
|
free software (you can get the source). Though there were earlier
|
|
version of ssed distributed, sites for these are not being listed.
|
|
|
|
http://sed.sourceforge.net/grabbag/ssed
|
|
http://freshmeat.net/project/sed/
|
|
|
|
GNU sed v4.0.5
|
|
This is the latest official version of GNU sed. It offers in-place
|
|
text replacement as an option switch.
|
|
|
|
ftp://ftp.gnu.org/pub/gnu/sed/sed-4.0.5.tar.gz
|
|
http://freshmeat.net/project/sed
|
|
|
|
BSD multi-byte sed (Japanese)
|
|
Based on the latest version of GNU sed, which supports multi-byte
|
|
characters.
|
|
|
|
ftp://ftp1.freebsd.org/pub/FreeBSD/FreeBSD-stable/packages/Latest/ja-sed.tgz
|
|
|
|
GNU sed v3.02.80
|
|
An alpha test release which was the base for the development of
|
|
ssed and GNU sed v4.0.
|
|
|
|
ftp://alpha.gnu.org/pub/gnu/sed/sed-3.02.80.tar.gz
|
|
|
|
GNU sed v3.02a
|
|
Interim version with most features of GNU sed v3.02.80.
|
|
|
|
GNU sed v3.02
|
|
ftp://ftp.gnu.org/pub/gnu/sed/sed-3.02.tar.gz
|
|
|
|
Precompiled versions:
|
|
|
|
GNU sed v3.02-8
|
|
source code and binaries for Debian GNU/Linux
|
|
|
|
http://www.debian.org/Packages/stable/base/sed.html
|
|
|
|
For some time, the GNU project <http://www.gnu.org> used Eric S.
|
|
Raymond's version of sed (ESR sed v1.1), but eventually dropped it
|
|
because it had too many built-in limits. In 1991 Howard Helman
|
|
modified the GNU/ESR sed and produced a flexible version of sed
|
|
v1.5 available at several sites (Helman's version permitted things
|
|
like \<...\> to delimit word boundaries, \xHH to enter hex code and
|
|
\n to indicate newlines in the replace string). This version did
|
|
not catch on with the GNU project and their version of sed has
|
|
moved in a similar but different direction.
|
|
|
|
sed v1.3, by Eric Steven Raymond (released 4 June 1998)
|
|
http://catb.org/~esr/sed-1.3.tar.gz
|
|
|
|
Eric Raymond <esr@snark.thyrsus.com> wrote one of the earliest
|
|
versions of sed. On his website <http://www.catb.org/~esr/> which
|
|
also distributes many freeware utilities he has written or worked
|
|
on, he describes sed v1.1 this way:
|
|
|
|
"This is the fast, small sed originally distributed in the GNU
|
|
toolkit and still distributed with Minix. The GNU people ditched it
|
|
when they built their own sed around an enhanced regex package --
|
|
but it's still better for some uses (in particular, faster and less
|
|
memory-intensive)." (Version 1.3 fixes an unidentified bug and adds
|
|
the L command to hexdump the current pattern space.)
|
|
|
|
2.2.1.2. OS/2
|
|
|
|
GNU sed v3.02.80
|
|
http://www2s.biglobe.ne.jp/~vtgf3mpr/gnu/sed.htm
|
|
|
|
GNU sed v3.02
|
|
http://hobbes.nmsu.edu/pub/os2/util/file/sed-3_02-r2-bin.zip # binaries
|
|
http://hobbes.nmsu.edu/pub/os2/util/file/sed-3_02-r2.zip # source
|
|
|
|
2.2.1.3. Microsoft Windows (Win3x, Win9x, WinNT, Win2K)
|
|
|
|
GNU sed v4.0.5
|
|
32-bit binaries and docs. Precompiled versions not available (yet).
|
|
|
|
GNU sed v3.02.80
|
|
32-bit binaries and docs, using DJGPP compiler. For details on new
|
|
features, see Unix section, above.
|
|
|
|
http://www.student.northpark.edu/pemente/sed/sed3028a.zip # DOS binaries
|
|
ftp://alpha.gnu.org/pub/gnu/sed/sed-3.02.80.tar.gz # source
|
|
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed3028b.zip # binaries
|
|
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed3028d.zip # docs
|
|
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed3028s.zip # source
|
|
|
|
GNU sed v2.05
|
|
32-bit binaries, no docs. Requires 80386 DX (SX will not run) and
|
|
must be run in a DOS window or in a full screen DOS session under
|
|
Microsoft Windows. Will not run in MS-DOS mode (outside Win/Win95).
|
|
We recommend using the latest version of GNU sed.
|
|
http://www.simtel.net/pub/win95/prog/gsed205b.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/win95/prog/gsed205b.zip
|
|
|
|
GNU sed v1.03
|
|
modified by Frank Whaley.
|
|
|
|
This version was part of the "Virtually UN*X" toolset, hosted by
|
|
itribe.net; that website is now closed. Gsed v1.03 supported Win9x
|
|
long filenames, as well as hex, decimal, binary, and octal
|
|
character representations.
|
|
|
|
The Cygwin toolkit:
|
|
http://www.cygwin.com
|
|
|
|
Formerly know as "GNU-Win32 tools." According to their home page,
|
|
"The Cygwin tools are Win32 ports of the popular GNU development
|
|
tools for Windows NT, 95 and 98. They function through the use of
|
|
the Cygwin library which provides a UNIX-like API on top of the
|
|
Win32 API." The version of sed used is GNU sed v3.02.
|
|
|
|
Minimalist GNU for Windows (MinGW):
|
|
http://www.mingw.org
|
|
http://mingw.sourceforge.net
|
|
|
|
According to their home page, "MinGW ('Minimalist GNU for Windows')
|
|
refers to a set of runtime headers, used in building a compiler
|
|
system based on the GNU GCC and binutils projects. It compiles and
|
|
links code to be run on Win32 platforms ... MinGW uses Microsoft
|
|
runtime libraries, distributed with the Windows operating system."
|
|
The version of sed used is GNU sed v3.02.
|
|
|
|
sed v1.5 (a/k/a HHsed), by Howard Helman
|
|
Compiled with Mingw32 for 32-bit environments described above. This
|
|
version should support Win95 long filenames.
|
|
http://www.dbnet.ece.ntua.gr/~george/sed/OLD/sed15.exe
|
|
http://www.student.northpark.edu/pemente/sed/sed15exe.zip
|
|
|
|
2.2.1.4. MS-DOS
|
|
|
|
sed v1.6 (from HHsed), by Walter Briscoe
|
|
|
|
This is a forthcoming version, now in beta testing, but with many
|
|
new features. It corrects all the bugs in sed v1.5, and adds the
|
|
best features of sedmod v1.0 (below). It is available in 16-bit and
|
|
32-bit compiled versions for MS-DOS. Sorry, no URLs available yet.
|
|
|
|
sed v1.5 (a/k/a HHsed), by Howard Helman
|
|
uncompiled source code (Turbo C)
|
|
ftp://ftp.simtel.net/pub/simtelnet/msdos/txtutl/sed15.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/msdos/txtutl/sed15.zip
|
|
|
|
DOS executable and documentation
|
|
ftp://ftp.simtel.net/pub/simtelnet/msdos/txtutl/sed15x.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/msdos/txtutl/sed15x.zip
|
|
|
|
sedmod v1.0, by Hern Chen
|
|
http://www.ptug.org/sed/SEDMOD10.ZIP
|
|
http://www.student.northpark.edu/pemente/sed/sedmod10.zip
|
|
ftp://garbo.uwasa.fi/pc/unix/sedmod10.zip
|
|
|
|
GNU sed v3.02.80
|
|
See section 2.2.1.3 ("Microsoft Windows"), above.
|
|
|
|
GNU sed v2.05
|
|
Does not run under MS-DOS.
|
|
|
|
GNU sed v1.18
|
|
32-bit binaries and source, using DJGPP compiler. Requires 80386 SX
|
|
or better. Also requires 3 CWS*.EXE extenders on the path. See
|
|
section 5.5 ("What is CSDPMI*B.ZIP and why do I need it?"), below.
|
|
We recommend using a newer version of GNU sed.
|
|
http://www.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed118b.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/gnu/djgpp/v2gnu/sed118b.zip
|
|
http://www.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/sed118s.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/gnu/djgpp/v2gnu/sed118s.zip
|
|
|
|
GNU sed v1.06
|
|
16-bit binaries and source. Should run under any MS-DOS system.
|
|
http://www.simtel.net/pub/gnu/gnuish/sed106.zip
|
|
ftp://ftp.cdrom.com/pub/simtelnet/gnu/gnuish/sed106.zip
|
|
|
|
2.2.1.5. CP/M
|
|
|
|
ssed v2.2, by Chuck A. Forsberg
|
|
|
|
Written for CP/M, ssed (for "small/stupid stream editor) supports
|
|
only the a(ppend), c(hange), d(elete) and i(nsert) options, and
|
|
apparently doesn't support regular expressions. A -u switch will
|
|
"unsqueeze" compressed files and was used mainly in conjunction
|
|
with DIF.COM for source code maintenance. (file: ssed22.lbr)
|
|
|
|
change, by Michael M. Rubenstein
|
|
|
|
Rubenstein released a version of sed called CHANGE.COM (the
|
|
TTOOLS.LBR archive member CHANGE.CZM is a "crunched" file).
|
|
CHANGE.COM supports full RE's except grouping and backreferences,
|
|
and its only function is global substitution. (file: ttools.lbr)
|
|
|
|
2.2.1.6. Macintosh v8 or v9
|
|
|
|
Since sed is a command-line utility, it is not customary to think
|
|
of sed being used on a Mac. Nonetheless, the following instructions
|
|
from Aurelio Jargas describe the process for running sed on MacOS
|
|
version version 8 or 9.
|
|
|
|
(1) Download and install the Apple DiskCopy application
|
|
|
|
ftp://ftp.apple.com/developer/Development_Kits
|
|
|
|
(2) Download and install Apple MPW
|
|
|
|
ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./
|
|
|
|
(3) Download and expand Matthias Neeracher's GNU sed for MPW. (They
|
|
seem to have misnumbered the sed filename.)
|
|
|
|
ftp://sunsite.cnlab-switch.ch/software/platform/macos/src/mpw_c/sed-2.03.sit.bin
|
|
|
|
(4) Enter the sed-3.02 directory and doubleclick the 'sed' file
|
|
|
|
(5) MPW Shell will open up. It will be a command window instead of
|
|
a command line, but sed should work as expected. For example:
|
|
|
|
echo aa | sed 's/a/Z/g'<ENTER>
|
|
|
|
Note that ENTER is different from RETURN on an iMac. Apple *also*
|
|
has its own version of sed on MPW, called "StreamEdit", with a
|
|
syntax fairly similar to that of normal sed.
|
|
|
|
2.2.2. Shareware and Commercial versions
|
|
|
|
2.2.2.1. Unix platforms
|
|
|
|
[ Additional information needed. ]
|
|
|
|
2.2.2.2. OS/2
|
|
|
|
Hamilton Labs:
|
|
http://www.hamiltonlabs.com/cshell.htm
|
|
|
|
A sizable set of Unix/C shell utilities designed for OS/2. Price is
|
|
$350 in the US, $395 elsewhere, with FedEx shipping, unconditional
|
|
guarantee, unlimited support and free updates. A demo version of
|
|
the suite can be downloaded from this site, but a stand-alone copy
|
|
of sed is not available.
|
|
|
|
2.2.2.3. Windows 95/98, Windows NT, Windows 2000
|
|
|
|
Hamilton Labs:
|
|
http://www.hamiltonlabs.com/cshell.htm
|
|
|
|
A sizable set of Unix/C shell utilities designed for Win9x, WinNT,
|
|
and Win2K. Price is $350 in the US, $395 elsewhere, with FedEx
|
|
shipping, unconditional guarantee, unlimited support and free
|
|
updates. A demo version of the suite can be downloaded from this
|
|
site, but a stand-alone copy of sed is not available.
|
|
|
|
Interix:
|
|
http://www.interix.com
|
|
|
|
Interix (formerly known as OpenNT) is advertised as "a complete
|
|
UNIX system environment running natively on Microsoft Windows NT",
|
|
and is licensed and supported by Softway Systems. It offers over
|
|
200 Unix utilities, and supports Unix shells, sockets, networking,
|
|
and more. A single-user edition runs about $200. A free demo or
|
|
evaluation copy will run for 31 days and then quit; to continue
|
|
using it, you must purchase the commercial version.
|
|
|
|
MKS NuTCRACKER Professional
|
|
http://www.datafocus.com/products/nutc/
|
|
|
|
A different, yet related product line offered by MKS (Mortice Kern
|
|
Systems, below); the awkward spelling "NuTCRACKER" is intentional.
|
|
Various packages offer hundreds of Unix utilities for Win32
|
|
environments. Sed is not available as a separate product.
|
|
|
|
UnixDos:
|
|
http://www.unixdos.com
|
|
|
|
UnixDos is a suite of 82 Unix utilities ported over to the Windows
|
|
environments. There are 16-bit versions for Win3.x and 32-bit
|
|
versions for WinNT/Win95. It is distributed as uncrippled shareware
|
|
for the first 30 days. After the test period, the utilities will
|
|
not run and you must pay the registration fee of $50.
|
|
|
|
Their version of sed supports "\n" in the RHS of expressions, and
|
|
increases the length of input lines to 10,000 characters. By
|
|
special arrangement with the owners, persons who want a licensed
|
|
version of sed *only* (without the other utilities) may pay a
|
|
license fee of $10.
|
|
|
|
U/WIN:
|
|
http://www.research.att.com/sw/tools/uwin/
|
|
|
|
U/WIN is a suite of Unix utilities created for WinNT and Win95
|
|
systems. It is owned by AT&T, created by David Korn (author of the
|
|
Unix korn shell), and is freely distributed only to educational
|
|
institutions, AT&T employees, or certain researchers; all others
|
|
must pay a fee after a 90-day evaluation period expires. U/WIN
|
|
operates best with the NTFS (WinNT file system) but will run in
|
|
degraded mode with the FAT file system and in further degraded mode
|
|
under Win95. A minimal installation takes about 25 to 30 megs of
|
|
disk space. Sed is not available as a separate file for download,
|
|
but comes with the suite.
|
|
|
|
2.2.2.4. MS-DOS
|
|
|
|
Mix C/Utilities Toolchest
|
|
http://www.mixsoftware.com/product/utility.htm
|
|
|
|
According to their web page, "The C/Utilities Toolchest adds over
|
|
40 powerful UNIX utilities to your MS-DOS operating system. The
|
|
result is an environment very similar to UNIX operating systems,
|
|
yet 100% compatible with MS-DOS programs and commands." The
|
|
toolchest costs $19.95, with source code available for an
|
|
additional fee. Mix C's version of sed is not available separately.
|
|
|
|
MKS (Mortice Kern Systems) Toolkit
|
|
http://www.mks.com
|
|
|
|
Sed comes bundled with the MKS Toolkit, which is distributed only
|
|
as commercial software; it is not available separately.
|
|
|
|
Thompson Automation Software
|
|
http://www.tasoft.com
|
|
|
|
The Thompson Toolkit contains over 100 familiar Unix utilities,
|
|
including a version of the Unix Korn shell. It runs under MS-DOS,
|
|
OS/2, Win3.x, Win9x, and WinNT. Sed is one of the utilities, though
|
|
Thompson is better known for its version of awk for DOS, TAWK. The
|
|
toolkit runs about $150; sed is not available separately.
|
|
|
|
2.3. Where can I learn to use sed?
|
|
|
|
2.3.1. Books
|
|
|
|
_Sed & Awk, 2d edition_, by Dale Dougherty & Arnold Robbins
|
|
(Sebastopol, Calif: O'Reilly and Associates, 1997)
|
|
ISBN 1-56592-225-5
|
|
http://www.oreilly.com/catalog/sed2/noframes.html
|
|
|
|
About 40 percent of this book is devoted to sed, and maybe 50
|
|
percent is devoted to awk. The other 10 percent covers regexes and
|
|
concepts common to both tools. If you prefer hard copy, this is
|
|
definitely the best single place to learn to use sed, including its
|
|
advanced features.
|
|
|
|
The first edition is also very useful. Several typos crept into the
|
|
first printing of the first edition (though if you follow the
|
|
tutorials closely, you'll recognize them right away). A list of
|
|
errors from the first printing of _sed & awk_ is available at
|
|
<http://www.cs.colostate.edu/~dzubera/sedawk.txt>, and errors in
|
|
the 2nd are at <http://www.cs.colostate.edu/~dzubera/sedawk2.txt>,
|
|
though most of these were corrected in later printings. The second
|
|
edition tells how POSIX standards have affected these tools and
|
|
covers the popular GNU versions of sed and awk. Price is about (US)
|
|
$30.00
|
|
|
|
-----
|
|
|
|
_Mastering Regular Expressions, 2d ed.,_ by Jeffrey E. F. Friedl
|
|
(Sebastopol, Calif: O'Reilly and Associates, 2002)
|
|
ISBN 0-596-00289-0
|
|
http://regex.info
|
|
http://www.oreilly.com/catalog/regex2/
|
|
http://public.yahoo.com/~jfriedl/regex/ (for the first edition)
|
|
|
|
Knowing how to use "regular expressions" is essential to effective
|
|
use of most Unix tools. This book focuses on how regular
|
|
expressions can be best implemented in utilities such as perl, vi,
|
|
emacs, and awk, but also touches on sed as well. Friedl's home page
|
|
(above) gives links to other sites which help students learn to
|
|
master regular expressions. His site also gives a Perl script for
|
|
determining a syntactically valid e-mail address, using regexes:
|
|
|
|
http://public.yahoo.com/~jfriedl/regex/code.html
|
|
|
|
-----
|
|
|
|
_Awk und Sed_, by Helmut Herold.
|
|
(Bonn: Addison-Wesley, 1994; 288 pages)
|
|
2nd edition to be released in March 2003
|
|
ISBN 3-8273-2094-1
|
|
http://www.addison-wesley.de/main/main.asp?page=home/bookdetails&ProductID=37214
|
|
|
|
2.3.2. Mailing list
|
|
|
|
If you are interested in learning more about sed (its syntax, using
|
|
regular expressions, etc.) you are welcome to subscribe to a
|
|
sed-oriented mailing list. In fact, there are two mailing lists
|
|
about sed: one in English named "sed-users", moderated by Sven
|
|
Guckes; and one in Portuguese named "sed-BR" (for sed-Brazil),
|
|
moderated by Aurelio Marinho Jargas. The average volume of mail for
|
|
"sed-users" is about 35 messages a week; the average volume of mail
|
|
for "sed-BR" is about 15 messages a week.
|
|
|
|
sed-BR mailing list: http://br.groups.yahoo.com/group/sed-br/
|
|
sed-users mailing list: http://groups.yahoo.com/group/sed-users/
|
|
|
|
To subscribe to sed-users, send a blank message to:
|
|
|
|
sed-users-subscribe@yahoogroups.com
|
|
|
|
To unsubscribe from sed-users, send a blank message to:
|
|
|
|
sed-users-unsubscribe@yahoogroups.com
|
|
|
|
2.3.3. Tutorials, electronic text
|
|
|
|
The original users manual for sed, by Lee E. McMahon, from the
|
|
7th edition UNIX Manual (1978), with the classic "Kubla Khan"
|
|
example and tutorial, in formatted text format:
|
|
http://sed.sourceforge.net/grabbag/tutorials/sed_mcmahon.txt
|
|
|
|
The source code to the preceding manual. Use "troff -ms sed" to
|
|
print this file properly:
|
|
http://plan9.bell-labs.com/7thEdMan/vol2/sed
|
|
http://cm.bell-labs.com/7thEdMan/vol2/sed
|
|
|
|
"Do It With Sed", by Carlos Duarte
|
|
http://www.dbnet.ece.ntua.gr/~george/sed/OLD/sedtut_1.html
|
|
|
|
"Sed: How to use sed, a special editor for modifying files
|
|
automatically", by Bruce Barnett and General Electric Company
|
|
http://www.grymoire.com/Unix/Sed.html
|
|
|
|
U-SEDIT2.ZIP, by Mike Arst (16 June 1990)
|
|
ftp://ftp.cs.umu.se/pub/pc/u-sedit2.zip
|
|
ftp://ftp.uni-stuttgart.de/pub/systems/msdos/util/unixlike/u-sedit2.zip
|
|
ftp://sunsite.icm.edu.pl/vol/wojsyl/garbo/pc/editor/u-sedit2.zip
|
|
ftp://ftp.sogang.ac.kr/pub/msdos/garbo_pc/editor/u-sedit2.zip
|
|
|
|
U-SEDIT3.ZIP, by Mike Arst (24 Jan. 1992)
|
|
http://www.student.northpark.edu/pemente/sed/u-sedit3.zip
|
|
CompuServe DTPFORUM, "PC DTP Utilities" library, file SEDDOC.ZIP
|
|
|
|
Another sed FAQ
|
|
http://www.dreamwvr.com/sed-info/sed-faq.html
|
|
|
|
sed-tutorial, by Felix von Leitner
|
|
http://www.math.fu-berlin.de/~leitner/sed/tutorial.html
|
|
|
|
"Manipulating text with sed," chapter 14 of the SCO OpenServer
|
|
"Operating System Users Guide"
|
|
http://ou800doc.caldera.com/SHL_automate/CTOC-Manipulating_text_with_sed.html
|
|
|
|
"Combining the Bourne-shell, sed and awk in the UNIX environment
|
|
for language analysis," by Lothar Schmitt and Kiel Christianson.
|
|
This basic tutorial on the Bourne shell, sed and awk downloads as a
|
|
71-page PostScript file (compressed to 290K with gzip). You may
|
|
need to navigate down from the root to get the file.
|
|
ftp://ftp.u-aizu.ac.jp/u-aizu/doc/Tech-Report/1997/97-2-007.tar.gz
|
|
available upon request from Lothar Schmitt <lothar@u-aizu.ac.jp>
|
|
|
|
2.3.4. General web and ftp sites
|
|
|
|
http://sed.sourceforge.net/grabbag # Collected scripts
|
|
http://main.rtfiber.com.tw/~changyj/sed/ # Yao-Jen Chang
|
|
http://www.math.fu-berlin.de/~guckes/sed/ # Sven Guckes
|
|
http://www.math.fu-berlin.de/~leitner/sed/ # Felix von Leitner
|
|
http://www.dbnet.ece.ntua.gr/~george/sed/ # Yiorgos Adamopoulos
|
|
http://www.student.northpark.edu/pemente/sed/ # Eric Pement
|
|
|
|
http://spacsun.rice.edu/FAQ/sed.html
|
|
ftp://algos.inesc.pt/pub/users/cdua/scripts.tar.gz (sed and shell scripts)
|
|
|
|
"Handy One-Liners For Sed", compiled by Eric Pement. A large list
|
|
of 1-line sed commands which can be executed from the command line.
|
|
http://sed.sourceforge.net/sed1line.txt
|
|
http://www.student.northpark.edu/pemente/sed/sed1line.txt
|
|
|
|
"Handy One-Liners For Sed", translated to Portuguese
|
|
http://wmaker.lrv.ufsc.br/sed_ptBR.html
|
|
|
|
The Single UNIX Specification, Version 3 (technical man page)
|
|
http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html
|
|
|
|
Getting started with sed
|
|
http://www.cs.hmc.edu/tech_docs/qref/sed.html
|
|
|
|
masm to gas converter
|
|
http://www.delorie.com/djgpp/faq/converting/asm2s-sed.html
|
|
|
|
mail2html.zip
|
|
http://www.crispen.org/src/#mail2html
|
|
|
|
sample uses of sed in batch files and scripts (Benny Pederson)
|
|
http://users.cybercity.dk/~bse26236/batutil/help/SED.HTM
|
|
|
|
dc.sed - the most complex and impressive sed script ever written.
|
|
This sed script by Greg Ubben emulates the Unix dc (desk
|
|
calculator), including base conversion, exponentiation, square
|
|
roots, and much more.
|
|
http://sed.sourceforge.net/grabbag/scripts/dc_overview.htm
|
|
|
|
If you should find other tutorials or scripts that should be added
|
|
to this document, please forward the URLs to the FAQ maintainer.
|
|
|
|
------------------------------
|
|
|
|
3. TECHNICAL
|
|
|
|
3.1. More detailed explanation of basic sed
|
|
|
|
Sed takes a script of editing commands and applies each command, in
|
|
order, to each line of input. After all the commands have been
|
|
applied to the first line of input, that line is output. A second
|
|
input line is taken for processing, and the cycle repeats. Sed
|
|
scripts can address a single line by line number or by matching a
|
|
/RE pattern/ on the line. An exclamation mark '!' after a regex
|
|
('/RE/!') or line number will select all lines that do NOT match
|
|
that address. Sed can also address a range of lines in the same
|
|
manner, using a comma to separate the 2 addresses.
|
|
|
|
$d # delete the last line of the file
|
|
/[0-9]\{3\}/p # print lines with 3 consecutive digits
|
|
5!s/ham/cheese/ # except on line 5, replace 'ham' with 'cheese'
|
|
/awk/!s/aaa/bb/ # unless 'awk' is found, replace 'aaa' with 'bb'
|
|
17,/foo/d # delete all lines from line 17 up to 'foo'
|
|
|
|
Following an address or address range, sed accepts curly braces
|
|
'{...}' so several commands may be applied to that line or to the
|
|
lines matched by the address range. On the command line, semicolons
|
|
';' separate each instruction and must precede the closing brace.
|
|
|
|
sed '/Owner:/{s/yours/mine/g;s/your/my/g;s/you/me/g;}' file
|
|
|
|
Range addresses operate differently depending on which version of
|
|
sed is used (see section 3.4, below). For further information on
|
|
using sed, consult the references in section 2.3, above.
|
|
|
|
3.1.1. Regular expressions on the left side of "s///"
|
|
|
|
All versions of sed support Basic Regular Expressions (BREs). For
|
|
the syntax of BREs, enter "man ed" at a Unix shell prompt. A
|
|
technical description of BREs from IEEE POSIX 1003.1-2001 and the
|
|
Single UNIX Specification Version 3 is available online at:
|
|
http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap09.html#tag_09_03
|
|
|
|
Sed normally supports BREs plus '\n' to match a newline in the
|
|
pattern space, plus '\xREx' as equivalent to '/RE/', where 'x' is any
|
|
character other than a newline or another backslash.
|
|
|
|
Some versions of sed support supersets of BREs, or "extended
|
|
regular expressions", which offer additional metacharacters for
|
|
increased flexibility. For additional information on extended REs
|
|
in GNU sed, see sections 3.7 ("GNU/POSIX extensions to regular
|
|
expressions") and 6.7.3 ("Special syntax in REs"), below.
|
|
|
|
Though not required by BREs, some versions of sed support \t to
|
|
represent a TAB, \r for carriage return, \xHH for direct entry of
|
|
hex codes, and so forth. Other versions of sed do not.
|
|
|
|
ssed (super-sed) introduced many new features for LHS pattern
|
|
matching, too many to give here. The complete list is found in
|
|
section 6.7.3.H ("ssed"), below.
|
|
|
|
3.1.2. Escape characters on the right side of "s///"
|
|
|
|
The right-hand side (the replacement part) in "s/find/replace/" is
|
|
almost always a string literal, with no interpolation of these
|
|
metacharacters:
|
|
|
|
. ^ $ [ ] { } ( ) ? + * |
|
|
|
|
Three things *are* interpolated: ampersand (&), backreferences, and
|
|
options for special seds. An ampersand on the RHS is replaced by
|
|
the entire expression matched on the LHS. There is _never_ any
|
|
reason to use grouping like this:
|
|
|
|
s/\(some-complex-regex\)/one two \1 three/
|
|
|
|
since you can do this instead:
|
|
|
|
s/some-complex-regex/one two & three/
|
|
|
|
To enter a literal ampersand on the RHS, type '\&'.
|
|
|
|
Grouping and backreferences: All versions of sed support grouping
|
|
and backreferences on the LHS and backreferences only on the RHS.
|
|
Grouping allows a series of characters to be collected in a set,
|
|
indicating the boundaries of the set with \( and \). Then the set
|
|
can be designated to be repeated a certain number of times
|
|
|
|
\(like this\)* or \(like this\)\{5,7\}.
|
|
|
|
Groups can also be nested "\(like \(this\) is here\)" and may
|
|
contain any valid RE. Backreferences repeat the contents of a
|
|
particular group, using a backslash and a digit (1-9) for each
|
|
corresponding group. In other words, "/\(pom\)\1/" is another way
|
|
of writing "/pompom/". If groups are nested, backreference numbers
|
|
are counted by matching \( in strict left to right order. Thus,
|
|
/..\(the \(word\)\) \("foo"\)../ is matched by the backreference
|
|
\3. Backreferences can be used in the LHS, the RHS, and in normal
|
|
RE addressing (see section 3.3). Thus,
|
|
|
|
/\(.\)\1\(.\)\2\(.\)\3/; # matches "bookkeeper"
|
|
/^\(.\)\(.\)\(.\)\3\2\1$/; # finds 6-letter palindromes
|
|
|
|
Seds differ in how they treat invalid backreferences where no
|
|
corresponding group occurs. To insert a literal ampersand or
|
|
backslash into the RHS, prefix it with a backslash: \& or \\.
|
|
|
|
ssed, sed16, and sedmod permit additional options on the RHS. They
|
|
all support changing part of the replacement string to upper case
|
|
(\u or \U), lower case (\l or \L), or to end case conversion (\E).
|
|
Both sed16 and sedmod support awk-style word references ($1, $2,
|
|
$3, ...) and $0 to insert the entire line before conversion.
|
|
|
|
echo ab ghi | sed16 "s/.*/$0 - \U$2/" # prints "ab ghi - GHI"
|
|
|
|
*Note:* This feature of sed16 and sedmod will break sed scripts which
|
|
put a dollar sign and digit into the RHS. Though this is an unlikely
|
|
combination, it's worth remembering if you use other people's scripts.
|
|
|
|
3.1.3. Substitution switches
|
|
|
|
Standard versions of sed support 4 main flags or switches which may
|
|
be added to the end of an "s///" command. They are:
|
|
|
|
N - Replace the Nth match of the pattern on the LHS, where
|
|
N is an integer between 1 and 512. If N is omitted,
|
|
the default is to replace the first match only.
|
|
g - Global replace of all matches to the pattern.
|
|
p - Print the results to stdout, even if -n switch is used.
|
|
w file - Write the pattern space to 'file' if a replacement was
|
|
done. If the file already exists when the script is
|
|
executed, it is overwritten. During script execution,
|
|
w appends to the file for each match.
|
|
|
|
GNU sed 3.02 and ssed also offer the /I switch for doing a
|
|
case-insensitive match. For example,
|
|
|
|
echo ONE TWO | gsed "s/one/unos/I" # prints "unos TWO"
|
|
|
|
GNU sed 4.x and ssed add the /M switch, to simplify working with
|
|
multi-line patterns: when it is used, ^ or $ will match BOL or EOL.
|
|
\` and \' remain available to match the start and end of pattern
|
|
space, respectively.
|
|
|
|
ssed supports two more switches, /S and /X, when its Perl mode is
|
|
used. They are described in detail in section 6.7.3.H, below.
|
|
|
|
3.1.4. Command-line switches
|
|
|
|
All versions of sed support two switches, -e and -n. Though sed
|
|
usually separates multiple commands with semicolons (e.g., "H;d;"),
|
|
certain commands could not accept a semicolon command separator.
|
|
These include :labels, 't', and 'b'. These commands had to occur
|
|
last in a script, separated by -e option switches. For example:
|
|
|
|
# The 'ta' means jump to label :a if last s/// returns true
|
|
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' file
|
|
|
|
The -n switch turns off sed's default behavior of printing every
|
|
line. With -n, lines are printed only if explicitly told to. In
|
|
addition, for certain versions of sed, if an external script begins
|
|
with "#n" as its first two characters, the output is suppressed
|
|
(exactly as if -n had been entered on the command line). A list of
|
|
which versions appears in section 6.7.2., below.
|
|
|
|
GNU sed 4.x and ssed support additional switches. -l (lowercase L),
|
|
followed by a number, lets you adjust the default length of the 'l'
|
|
and 'L' commands (note that these implementations of sed also
|
|
support an argument to these commands, to tailor the length
|
|
separately of each occurrence of the command).
|
|
|
|
-i activates in-place editing (see section 4.41.1, below). -s
|
|
treats each file as a separate stream: sed by default joins all the
|
|
files, so $ represents the last line of the last file; 15 means the
|
|
15th line in the joined stream; and /abc/,/def/ might match across
|
|
files.
|
|
|
|
When -s is used, however all addresses refer to single files. For
|
|
example, $ represents the last line of each input file; 15 means
|
|
the 15th line of each input file; and /abc/,/def/ will be "reset"
|
|
(in other words, sed will not execute the commands and start
|
|
looking for /abc/ again) if a file ends before /def/ has been
|
|
matched. Note that -i automatically activates this interpretation
|
|
of addresses.
|
|
|
|
3.2. Common one-line sed scripts
|
|
|
|
A separate document of over 70 handy "one-line" sed commands is
|
|
available at
|
|
http://sed.sourceforge.net/sed1line.txt
|
|
|
|
Here are several common sed commands for one-line use. MS-DOS users
|
|
should replace single quotes ('...') with double quotes ("...") in
|
|
these examples. A specific filename usually follows the script,
|
|
though the input may also come via piping or redirection.
|
|
|
|
# Double space a file
|
|
sed G file
|
|
|
|
# Triple space a file
|
|
sed 'G;G' file
|
|
|
|
# Under UNIX: convert DOS newlines (CR/LF) to Unix format
|
|
sed 's/.$//' file # assumes that all lines end with CR/LF
|
|
sed 's/^M$// file # in bash/tcsh, press Ctrl-V then Ctrl-M
|
|
|
|
# Under DOS: convert Unix newlines (LF) to DOS format
|
|
sed 's/$//' file # method 1
|
|
sed -n p file # method 2
|
|
|
|
# Delete leading whitespace (spaces/tabs) from front of each line
|
|
# (this aligns all text flush left). '^t' represents a true tab
|
|
# character. Under bash or tcsh, press Ctrl-V then Ctrl-I.
|
|
sed 's/^[ ^t]*//' file
|
|
|
|
# Delete trailing whitespace (spaces/tabs) from end of each line
|
|
sed 's/[ ^t]*$//' file # see note on '^t', above
|
|
|
|
# Delete BOTH leading and trailing whitespace from each line
|
|
sed 's/^[ ^t]*//;s/[ ^]*$//' file # see note on '^t', above
|
|
|
|
# Substitute "foo" with "bar" on each line
|
|
sed 's/foo/bar/' file # replaces only 1st instance in a line
|
|
sed 's/foo/bar/4' file # replaces only 4th instance in a line
|
|
sed 's/foo/bar/g' file # replaces ALL instances within a line
|
|
|
|
# Substitute "foo" with "bar" ONLY for lines which contain "baz"
|
|
sed '/baz/s/foo/bar/g' file
|
|
|
|
# Delete all CONSECUTIVE blank lines from file except the first.
|
|
# This method also deletes all blank lines from top and end of file.
|
|
# (emulates "cat -s")
|
|
sed '/./,/^$/!d' file # this allows 0 blanks at top, 1 at EOF
|
|
sed '/^$/N;/\n$/D' file # this allows 1 blank at top, 0 at EOF
|
|
|
|
# Delete all leading blank lines at top of file (only).
|
|
sed '/./,$!d' file
|
|
|
|
# Delete all trailing blank lines at end of file (only).
|
|
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' file
|
|
|
|
# If a line ends with a backslash, join the next line to it.
|
|
sed -e :a -e '/\\$/N; s/\\\n//; ta' file
|
|
|
|
# If a line begins with an equal sign, append it to the previous
|
|
# line (and replace the "=" with a single space).
|
|
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D' file
|
|
|
|
3.3. Addressing and address ranges
|
|
|
|
Sed commands may have an optional "address" or "address range"
|
|
prefix. If there is no address or address range given, then the
|
|
command is applied to all the lines of the input file or text
|
|
stream. Three commands cannot take an address prefix:
|
|
|
|
- labels, used to branch or jump within the script
|
|
- the close brace, '}', which ends the '{' "command"
|
|
- the '#' comment character, also technically a "command"
|
|
|
|
An address can be a line number (such as 1, 5, 37, etc.), a regular
|
|
expression (written in the form /RE/ or \xREx where 'x' is any
|
|
character other than '\' and RE is the regular expression), or the
|
|
dollar sign ($), representing the last line of the file. An
|
|
exclamation mark (!) after an address or address range will apply
|
|
the command to every line EXCEPT the ones named by the address. A
|
|
null regex ("//") will be replaced by the last regex which was
|
|
used. Also, some seds do not support \xREx as regex delimiters.
|
|
|
|
5d # delete line 5 only
|
|
5!d # delete every line except line 5
|
|
/RE/s/LHS/RHS/g # substitute only if RE occurs on the line
|
|
/^$/b label # if the line is blank, branch to ':label'
|
|
/./!b label # ... another way to write the same command
|
|
\%.%!b label # ... yet another way to write this command
|
|
$!N # on all lines but the last, get the Next line
|
|
|
|
Note that an embedded newline can be represented in an address by
|
|
the symbol \n, but this syntax is needed only if the script puts 2
|
|
or more lines into the pattern space via the N, G, or other
|
|
commands. The \n symbol does *not* match the newline at an
|
|
end-of-line because when sed reads each line into the pattern space
|
|
for processing, it strips off the trailing newline, processes the
|
|
line, and adds a newline back when printing the line to standard
|
|
output. To match the end-of-line, use the '$' metacharacter, as
|
|
follows:
|
|
|
|
/tape$/ # matches the word 'tape' at the end of a line
|
|
/tape$deck/ # matches the word 'tape$deck' with a literal '$'
|
|
/tape\ndeck/ # matches 'tape' and 'deck' with a newline between
|
|
|
|
The following sed commands usually accept *only* a single address.
|
|
All other commands (except labels, '}', and '#') accept both single
|
|
addresses and address ranges.
|
|
|
|
= print to stdout the line number of the current line
|
|
a after printing the current line, append "text" to stdout
|
|
i before printing the current line, insert "text" to stdout
|
|
q quit after the current line is matched
|
|
r file prints contents of "file" to stdout after line is matched
|
|
|
|
Note that we said "usually." If you need to apply the '=', 'a',
|
|
'i', or 'r' commands to each and every line within an address
|
|
range, this behavior can be coerced by the use of braces. Thus,
|
|
"1,9=" is an invalid command, but "1,9{=;}" will print each line
|
|
number followed by its line for the first 9 lines (and then print
|
|
the rest of the rest of the file normally).
|
|
|
|
Address ranges occur in the form
|
|
|
|
<address1>,<address2> or <address1>,<address2>!
|
|
|
|
where the address can be a line number or a standard /regex/.
|
|
<address2> can also be a dollar sign, indicating the end of file.
|
|
Under GNU sed 3.02+, ssed, and sed15+, <address2> may also be a
|
|
notation of the form +num, indicating the next _num_ lines after
|
|
<address1> is matched.
|
|
|
|
Address ranges are:
|
|
|
|
(1) Inclusive. The range "/From here/,/eternity/" matches all the
|
|
lines containing "From here" up to and including the line
|
|
containing "eternity". It will not stop on the line just prior to
|
|
"eternity". (If you don't like this, see section 4.24.)
|
|
|
|
(2) Plenary. They always match full lines, not just parts of lines.
|
|
In other words, a command to change or delete an address range will
|
|
change or delete whole lines; it won't stop in the middle of a
|
|
line.
|
|
|
|
(3) Multi-linear. Address ranges normally match 2 lines or more.
|
|
The second address will never match the same line the first address
|
|
did; therefore a valid address range always spans at least two
|
|
lines, with these exceptions which match only one line:
|
|
|
|
- if the first address matches the last line of the file
|
|
- if using the syntax "/RE/,3" and /RE/ occurs only once in the
|
|
file at line 3 or below
|
|
- if using HHsed v1.5. See section 3.4.
|
|
|
|
(4) Minimalist. In address ranges with /regex/ as <address2>, the
|
|
range "/foo/,/bar/" will stop at the first "bar" it finds, provided
|
|
that "bar" occurs on a line below "foo". If the word "bar" occurs
|
|
on several lines below the word "foo", the range will match all the
|
|
lines from the first "foo" up to the first "bar". It will not
|
|
continue hopping ahead to find more "bar"s. In other words, address
|
|
ranges are not "greedy," like regular expressions.
|
|
|
|
(5) Repeating. An address range will try to match more than one
|
|
block of lines in a file. However, the blocks cannot nest. In
|
|
addition, a second match will not "take" the last line of the
|
|
previous block. For example, given the following text,
|
|
|
|
start
|
|
stop start
|
|
stop
|
|
|
|
the sed command '/start/,/stop/d' will only delete the first two
|
|
lines. It will not delete all 3 lines.
|
|
|
|
(6) Relentless. If the address range finds a "start" match but
|
|
doesn't find a "stop", it will match every line from "start" to the
|
|
end of the file. Thus, beware of the following behaviors:
|
|
|
|
/RE1/,/RE2/ # If /RE2/ is not found, matches from /RE1/ to the
|
|
# end-of-file.
|
|
|
|
20,/RE/ # If /RE/ is not found, matches from line 20 to the
|
|
# end-of-file.
|
|
|
|
/RE/,30 # If /RE/ occurs any time after line 30, each
|
|
# occurrence will be matched in sed15+, sedmod, and
|
|
# GNU sed v3.02+. GNU sed v2.05 and 1.18 will match
|
|
# from the 2nd occurrence of /RE/ to the end-of-file.
|
|
|
|
If these behaviors seem strange, remember that they occur because
|
|
sed does not look "ahead" in the file. Doing so would stop sed from
|
|
being a stream editor and have adverse effects on its efficiency.
|
|
If these behaviors are undesirable, they can be circumvented or
|
|
corrected by the use of nested testing within braces. The following
|
|
scripts work under GNU sed 3.02:
|
|
|
|
# Execute your_commands on range "/RE1/,/RE2/", but if /RE2/ is
|
|
# not found, do nothing.
|
|
/RE1/{:a;N;/RE2/!ba;your_commands;}
|
|
|
|
# Execute your_commands on range "20,/RE/", but if /RE/ is not
|
|
# found, do nothing.
|
|
20{:a;N;/RE/!ba;your_commands;}
|
|
|
|
As a side note, once we've used N to "slurp" lines together to test
|
|
for the ending expression, the pattern space will have gathered
|
|
many lines (possibly thousands) together and concatenated them as a
|
|
single expression, with the \n sequence marking line breaks. The
|
|
REs *within* the pattern space may have to be modified (e.g., you
|
|
must write '/\nStart/' instead of '/^Start/' and '/[^\n]*/' instead
|
|
of '/.*/') and other standard sed commands will be unavailable or
|
|
difficult to use.
|
|
|
|
# Execute your_commands on range "/RE/,30", but if /RE/ occurs
|
|
# on line 31 or later, do not match it.
|
|
1,30{/RE/,$ your_commands;}
|
|
|
|
For related suggestions on using address ranges, see sections 4.2,
|
|
4.15, and 4.19 of this FAQ. Also, note the following section.
|
|
|
|
3.4. Address ranges in GNU sed and HHsed
|
|
|
|
(1) GNU sed 3.02+, ssed, and sed15+ all support address ranges like:
|
|
|
|
/regex/,+5
|
|
|
|
which match /regex/ plus the next 5 lines (or EOF, whichever comes
|
|
first).
|
|
|
|
(2) GNU sed v3.02.80 (and above) and ssed support address ranges of:
|
|
|
|
0,/regex/
|
|
|
|
as a special case to permit matching /regex/ if it occurs on the
|
|
first line. This syntax permits a range expression that matches
|
|
every line from the top of the file to the first instance of
|
|
/regex/, even if /regex/ is on the first line.
|
|
|
|
(3) HHsed (sed15) has an exceptional way of implementing
|
|
|
|
/regex1/,/regex2/
|
|
|
|
If /RE1/ and /RE2/ both occur on the *same* line, HHsed will match
|
|
that single line. In other words, an address range block can
|
|
consist of just one line. HHsed will then look for the next
|
|
occurrence of /regex1/ to begin the block again.
|
|
|
|
Every other version of sed (including sed16) requires 2 lines to
|
|
match an address range, and thus /regex1/ and /regex2/ cannot
|
|
successfully match just one line. See also the comments at
|
|
section 7.9.4, below.
|
|
|
|
(4) BEGIN~STEP selection: ssed and GNU sed (v2.05 and above) offer
|
|
a form of addressing called "BEGIN~STEP selection". This is *not* a
|
|
range address, which selects an inclusive block of consecutive
|
|
lines from /start/ to /finish/. But I think it seems to belong here.
|
|
|
|
Given an expression of the form "M~N", where M and N are integers,
|
|
GNU sed and ssed will select every Nth line, beginning at line M.
|
|
(With gsed v2.05, M had to be less than N, but this restriction is
|
|
no longer necessary). Both M and N may equal 0 ("0~0" selects every
|
|
line). These examples illustrate the syntax:
|
|
|
|
sed '1~3d' file # delete every 3d line, starting with line 1
|
|
# deletes lines 1, 4, 7, 10, 13, 16, ...
|
|
|
|
sed '0~3d' file # deletes lines 3, 6, 9, 12, 15, 18, ...
|
|
|
|
sed -n '2~5p' file # print every 5th line, starting with line 2
|
|
# prints lines 2, 7, 12, 17, 22, 27, ...
|
|
|
|
(5) Finally, GNU sed v2.05 has a bug in range addressing (see
|
|
section 7.5), which was fixed in the higher versions.
|
|
|
|
|
|
3.5. Debugging sed scripts
|
|
|
|
The following two debuggers should make it easier to understand how
|
|
sed scripts operate. They can save hours of grief when trying to
|
|
determine the problems with a sed script.
|
|
|
|
(1) sd (sed debugger), by Brian Hiles
|
|
|
|
This debugger runs under a Unix shell, is powerful, and is easy to
|
|
use. sd has conditional breakpoints and spypoints of the pattern
|
|
space and hold space, on any scope defined by regex match and/or
|
|
script line number. It can be semi-automated, can save diagnostic
|
|
reports, and shows potential problems with a sed script before it
|
|
tries to execute it. The script is robust and requires the Unix
|
|
shell utilities plus the Bourne shell or Korn shell to execute.
|
|
|
|
http://sed.sourceforge.net/grabbag/scripts/sd.ksh.txt (2003)
|
|
http://sed.sourceforge.net/grabbag/scripts/sd.sh.txt (1998)
|
|
|
|
(2) sedsed, by Aurelio Jargas
|
|
|
|
This debugger requires Python to run it, and it uses your own
|
|
version of sed, whatever that may be. It displays the current input
|
|
line, the pattern space, and the hold space, before and after each
|
|
sed command is executed.
|
|
|
|
http://sedsed.sourceforge.net
|
|
|
|
|
|
3.6. Notes about s2p, the sed-to-perl translator
|
|
|
|
s2p (sed to perl) is a Perl program to convert sed scripts into the
|
|
Perl programming language; it is included with many versions of
|
|
Perl. These problems have been found when using s2p:
|
|
|
|
(1) Doesn't recognize the semicolon properly after s/// commands.
|
|
|
|
s/foo/bar/g;
|
|
|
|
(2) Doesn't trim trailing whitespace after s/// commands. Even lone
|
|
trailing spaces, without comments, produce an error.
|
|
|
|
(3) Doesn't handle multiple commands within braces. E.g.,
|
|
|
|
1,4{=;G;}
|
|
|
|
will produce perl code with missing braces, and miss the second "G"
|
|
command as well. In fact, any commands after the first one are
|
|
missed in the perl output script, and the output perl script will
|
|
also contain mismatched braces.
|
|
|
|
3.7. GNU/POSIX extensions to regular expressions
|
|
|
|
GNU sed supports "character classes" in addition to regular
|
|
character sets, such as [0-9A-F]. Like regular character sets,
|
|
character classes represent any single character within a set.
|
|
|
|
"Character classes are a new feature introduced in the POSIX
|
|
standard. A character class is a special notation for describing
|
|
lists of characters that have a specific attribute, but where the
|
|
actual characters themselves can vary from country to country
|
|
and/or from character set to character set. For example, the notion
|
|
of what is an alphabetic character differs in the USA and in
|
|
France." [quoted from the docs for GNU awk v3.1.0.]
|
|
|
|
Though character classes don't generally conserve space on the
|
|
line, they help make scripts portable for international use. The
|
|
equivalent character sets _for U.S. users_ follows:
|
|
|
|
[[:alnum:]] - [A-Za-z0-9] Alphanumeric characters
|
|
[[:alpha:]] - [A-Za-z] Alphabetic characters
|
|
[[:blank:]] - [ \x09] Space or tab characters only
|
|
[[:cntrl:]] - [\x00-\x19\x7F] Control characters
|
|
[[:digit:]] - [0-9] Numeric characters
|
|
[[:graph:]] - [!-~] Printable and visible characters
|
|
[[:lower:]] - [a-z] Lower-case alphabetic characters
|
|
[[:print:]] - [ -~] Printable (non-Control) characters
|
|
[[:punct:]] - [!-/:-@[-`{-~] Punctuation characters
|
|
[[:space:]] - [ \t\v\f] All whitespace chars
|
|
[[:upper:]] - [A-Z] Upper-case alphabetic characters
|
|
[[:xdigit:]] - [0-9a-fA-F] Hexadecimal digit characters
|
|
|
|
Note that [[:graph:]] does not match the space " ", but [[:print:]]
|
|
does. Some character classes may (or may not) match characters in
|
|
the high ASCII range (ASCII 128-255 or 0x80-0xFF), depending on
|
|
which C library was used to compile sed. For non-English languages,
|
|
[[:alpha:]] and other classes may also match high ASCII characters.
|
|
|
|
------------------------------
|
|
|
|
4. EXAMPLES
|
|
|
|
ONE-CHARACTER QUESTIONS
|
|
|
|
4.1. How do I insert a newline into the RHS of a substitution?
|
|
|
|
Several versions of sed permit '\n' to be typed directly into the
|
|
RHS, which is then converted to a newline on output: ssed,
|
|
gsed302a+, gsed103 (with the -x switch), sed15+, sedmod, and
|
|
UnixDOS sed. The _easiest_ solution is to use one of these
|
|
versions.
|
|
|
|
For other versions of sed, try one of the following:
|
|
|
|
(a) If typing the sed script from a Bourne shell, use one backslash
|
|
"\" if the script uses 'single quotes' or two backslashes "\\" if
|
|
the script requires "double quotes". In the example below, note
|
|
that the leading '>' on the 2nd line is generated by the shell to
|
|
prompt the user for more input. The user types in slash,
|
|
single-quote, and then ENTER to terminate the command:
|
|
|
|
[sh-prompt]$ echo twolines | sed 's/two/& new\
|
|
>/'
|
|
two new
|
|
lines
|
|
[bash-prompt]$
|
|
|
|
(b) Use a script file with one backslash '\' in the script,
|
|
immediately followed by a newline. This will embed a newline into
|
|
the "replace" portion. Example:
|
|
|
|
sed -f newline.sed files
|
|
|
|
# newline.sed
|
|
s/twolines/two new\
|
|
lines/g
|
|
|
|
Some versions of sed may not need the trailing backslash. If so,
|
|
remove it.
|
|
|
|
(c) Insert an unused character and pipe the output through tr:
|
|
|
|
echo twolines | sed 's/two/& new=/' | tr "=" "\n" # produces
|
|
two new
|
|
lines
|
|
|
|
(d) Use the "G" command:
|
|
|
|
G appends a newline, plus the contents of the hold space to the end
|
|
of the pattern space. If the hold space is empty, a newline is
|
|
appended anyway. The newline is stored in the pattern space as "\n"
|
|
where it can be addressed by grouping "\(...\)" and moved in the
|
|
RHS. Thus, to change the "twolines" example used earlier, the
|
|
following script will work:
|
|
|
|
sed '/twolines/{G;s/\(two\)\(lines\)\(\n\)/\1\3\2/;}'
|
|
|
|
(e) Inserting full lines, not breaking lines up:
|
|
|
|
If one is not *changing* lines but only inserting complete lines
|
|
before or after a pattern, the procedure is much easier. Use the
|
|
"i" (insert) or "a" (append) command, making the alterations by an
|
|
external script. To insert "This line is new" BEFORE each line
|
|
matching a regex:
|
|
|
|
/RE/i This line is new # HHsed, sedmod, gsed 3.02a
|
|
/RE/{x;s/$/This line is new/;G;} # other seds
|
|
|
|
The two examples above are intended as "one-line" commands entered
|
|
from the console. If using a sed script, "i\" immediately followed
|
|
by a literal newline will work on all versions of sed. Furthermore,
|
|
the command "s/$/This line is new/" will only work if the hold
|
|
space is already empty (which it is by default).
|
|
|
|
To append "This line is new" AFTER each line matching a regex:
|
|
|
|
/RE/a This line is new # HHsed, sedmod, gsed 3.02a
|
|
/RE/{G;s/$/This line is new/;} # other seds
|
|
|
|
To append 2 blank lines after each line matching a regex:
|
|
|
|
/RE/{G;G;} # assumes the hold space is empty
|
|
|
|
To replace each line matching a regex with 5 blank lines:
|
|
|
|
/RE/{s/.*//;G;G;G;G;} # assumes the hold space is empty
|
|
|
|
(f) Use the "y///" command if possible:
|
|
|
|
On some Unix versions of sed (not GNU sed!), though the s///
|
|
command won't accept '\n' in the RHS, the y/// command does. If
|
|
your Unix sed supports it, a newline after "aaa" can be inserted
|
|
this way (which is not portable to GNU sed or other seds):
|
|
|
|
s/aaa/&~/; y/~/\n/; # assuming no other '~' is on the line!
|
|
|
|
4.2. How do I represent control-codes or nonprintable characters?
|
|
|
|
Several versions of sed support the notation \xHH, where "HH" are
|
|
two hex digits, 00-FF: ssed, GNU sed v3.02.80 and above, GNU sed
|
|
v1.03, sed16 and sed15 (HHsed). Try to use one of those versions.
|
|
|
|
Sed is not intended to process binary or object code, and files
|
|
which contain nulls (0x00) will usually generate errors in most
|
|
versions of sed. The latest versions of GNU sed and ssed are an
|
|
exception; they permit nulls in the input files and also in
|
|
regexes.
|
|
|
|
On Unix platforms, the 'echo' command may allow insertion of octal
|
|
or hex values, e.g., `echo "\0nnn"` or `echo -n "\0nnn"`. The echo
|
|
command may also support syntax like '\\b' or '\\t' for backspace
|
|
or tab characters. Check the man pages to see what syntax your
|
|
version of echo supports. Some versions support the following:
|
|
|
|
# replace 0x1A (32 octal) with ASCII letters
|
|
sed 's/'`echo "\032"`'/Ctrl-Z/g'
|
|
|
|
# note the 3 backslashes in the command below
|
|
sed "s/.`echo \\\b`//g"
|
|
|
|
4.3. How do I convert files with toggle characters, like +this+, to
|
|
look like [i]this[/i]?
|
|
|
|
Input files, especially message-oriented text files, often contain
|
|
toggle characters for emphasis, like ~this~, *this*, or =this=. Sed
|
|
can make the same input pattern produce alternating output each
|
|
time it is encountered. Typical needs might be to generate HMTL
|
|
codes or print codes for boldface, italic, or underscore. This
|
|
script accomodates multiple occurrences of the toggle pattern on
|
|
the same line, as well as cases where the pattern starts on one
|
|
line and finishes several lines later, even at the end of the file:
|
|
|
|
# sed script to convert +this+ to [i]this[/i]
|
|
:a
|
|
/+/{ x; # If "+" is found, switch hold and pattern space
|
|
/^ON/{ # If "ON" is in the (former) hold space, then ..
|
|
s///; # .. delete it
|
|
x; # .. switch hold space and pattern space back
|
|
s|+|[/i]|; # .. turn the next "+" into "[/i]"
|
|
ba; # .. jump back to label :a and start over
|
|
}
|
|
s/^/ON/; # Else, "ON" was not in the hold space; create it
|
|
x; # Switch hold space and pattern space
|
|
s|+|[i]|; # Turn the first "+" into "[i]"
|
|
ba; # Branch to label :a to find another pattern
|
|
}
|
|
#---end of script---
|
|
|
|
This script uses the hold space to create a "flag" to indicate
|
|
whether the toggle is ON or not. We have added remarks to
|
|
illustrate the script logic, but in most versions of sed remarks
|
|
are not permitted after 'b'ranch commands or labels.
|
|
|
|
If you are sure that the +toggle+ characters never cross line
|
|
boundaries (i.e., never begin on one line and end on another), this
|
|
script can be reduced to one line:
|
|
|
|
s|+\([^+][^+]*\)+|[i]\1[/i]|g
|
|
|
|
If your toggle pattern contains regex metacharacters (such as '*'
|
|
or perhaps '+' or '?'), remember to quote them with backslashes.
|
|
|
|
CHANGING STRINGS
|
|
|
|
4.10. How do I perform a case-insensitive search?
|
|
|
|
Several versions of sed support case-insensitive matching: ssed and
|
|
GNU sed v3.02+ (with I flag after s/// or /regex/); sedmod with the
|
|
-i switch; and sed16 (which supports both types of switches).
|
|
|
|
With other versions of sed, case-insensitive searching is awkward,
|
|
so people may use awk or perl instead, since these programs have
|
|
options for case-insensitive searches. In gawk/mawk, use "BEGIN
|
|
{IGNORECASE=1}" and in perl, "/regex/i". For other seds, here are
|
|
three solutions:
|
|
|
|
Solution 1: convert everything to upper case and search normally
|
|
|
|
# sed script, solution 1
|
|
h; # copy the original line to the hold space
|
|
# convert the pattern space to solid caps
|
|
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
|
|
# now we can search for the word "CARLOS"
|
|
/CARLOS/ {
|
|
# add or insert lines. Note: "s/.../.../" will not work
|
|
# here because we are searching a modified pattern
|
|
# space and are not printing the pattern space.
|
|
}
|
|
x; # get back the original pattern space
|
|
# the original pattern space will be printed
|
|
#---end of sed script---
|
|
|
|
Solution 2: search for both cases
|
|
|
|
Often, proper names will either start with all lower-case ("unix"),
|
|
with an initial capital letter ("Unix") or occur in solid caps
|
|
("UNIX"). There may be no need to search for every possibility.
|
|
|
|
/UNIX/b match
|
|
/[Uu]nix/b match
|
|
|
|
Solution 3: search for all possible cases
|
|
|
|
# If you must, search for any possible combination
|
|
/[Ca][Aa][Rr][Ll][Oo][Ss]/ { ... }
|
|
|
|
Bear in mind that as the pattern length increases, this solution
|
|
becomes an order of magnitude slower than the one of Solution 1, at
|
|
least with some implementations of sed.
|
|
|
|
4.11. How do I match only the first occurrence of a pattern?
|
|
|
|
(1) The general solution is to use GNU sed or ssed, with one of
|
|
these range expressions. The first script ("print only the first
|
|
match") works with any version of sed:
|
|
|
|
sed -n '/RE/{p;q;}' file # print only the first match
|
|
sed '0,/RE/{//d;}' file # delete only the first match
|
|
sed '0,/RE/s//to_that/' file # change only the first match
|
|
|
|
(2) If you cannot use GNU sed and if you *know* the pattern will
|
|
not occur on the first line, this will work:
|
|
|
|
sed '1,/RE/{//d;}' file # delete only the first match
|
|
sed '1,/RE/s//to_that/' file # change only the first match
|
|
|
|
(3) If you cannot use GNU sed and the pattern *might* occur on the
|
|
first line, use one of the following commands (credit for short GNU
|
|
script goes to Donald Bruce Stewart):
|
|
|
|
sed '/RE/{x;/Y/!{s/^/Y/;h;d;};x;}' file # delete (one way)
|
|
sed -e '/RE/{d;:a' -e '$!N;$ba' -e '}' file # delete (another way)
|
|
sed '/RE/{d;:a;N;$ba;}' file # same script, GNU sed
|
|
sed -e '/RE/{s//to_that/;:a' -e '$!N;$!ba' -e '}' file # change
|
|
|
|
Still another solution, using a flag in the hold space. This is
|
|
portable to all seds and works if the pattern is on the first line:
|
|
|
|
# sed script to change "foo" to "bar" only on the first occurrence
|
|
1{x;s/^/first/;x;}
|
|
1,/foo/{x;/first/s///;x;s/foo/bar/;}
|
|
#---end of script---
|
|
|
|
4.12. How do I parse a comma-delimited (CSV) data file?
|
|
|
|
Comma-delimited data files can come in several forms, requiring
|
|
increasing levels of complexity in parsing and handling. They are
|
|
often referred to as CSV files (for "comma separated values") and
|
|
occasionally as SDF files (for "standard data format"). Note that
|
|
some vendors use "SDF" to refer to variable-length records with
|
|
comma-separated fields which are "double-quoted" if they contain
|
|
character values, while other vendors use "SDF" to designate
|
|
fixed-length records with fixed-length, nonquoted fields! (For help
|
|
with fixed-length fields, see question 4.23)
|
|
|
|
The term "CSV" became a de-facto standard when Microsoft Excel used
|
|
it as an optional output file format.
|
|
|
|
Here are 4 different forms you may encounter in comma-delimited data:
|
|
|
|
(a) No quotes, no internal commas
|
|
|
|
1001,John Smith,PO Box 123,Chicago,IL,60699
|
|
1002,Mary Jones,320 Main,Denver,CO,84100,
|
|
|
|
(b) Like (a), with quotes around each field
|
|
|
|
"1003","John Smith","PO Box 123","Chicago","IL","60699"
|
|
"1004","Mary Jones","320 Main","Denver","CO","84100"
|
|
|
|
(c) Like (b), with embedded commas
|
|
|
|
"1005","Tom Hall, Jr.","61 Ash Ct.","Niles","OH","44446"
|
|
"1006","Bob Davis","429 Pine, Apt. 5","Boston","MA","02128"
|
|
|
|
(d) Like (c), with embedded commas and quotes
|
|
|
|
"1007","Sue "Red" Smith","19 Main","Troy","MI","48055"
|
|
"1008","Joe "Hey, guy!" Hall","POB 44","Reno","NV","89504"
|
|
|
|
In each example above, we have 7 fields and 6 commas which function
|
|
as field separators. Case (c) is a very typical form of these data
|
|
files, with double quotes used to enclose each field and to protect
|
|
internal commas (such as "Tom Hall, Jr.") from interpretation as
|
|
field separators. However, many times the data may include both
|
|
embedded quotation marks as well as embedded commas, as seen by
|
|
case (d), above.
|
|
|
|
Case (d) is the closest to Microsoft CSV format. *However*, the
|
|
Microsoft CSV format allows embedded newlines within a
|
|
double-quoted field. If embedded newlines within fields are a
|
|
possibility for your data, you should consider using something
|
|
other than sed to work with the data file.
|
|
|
|
Before handling a comma-delimited data file, make sure that you
|
|
fully understand its format and check the integrity of the data.
|
|
Does each line contain the same number of fields? Should certain
|
|
fields be composed only of numbers or of two-letter state
|
|
abbreviations in all caps? Sed (or awk or perl) should be used to
|
|
validate the integrity of the data file before you attempt to alter
|
|
it or extract particular fields from the file.
|
|
|
|
After ensuring that each line has a valid number of fields, use sed
|
|
to locate and modify individual fields, using the \(...\) grouping
|
|
command where needed.
|
|
|
|
In case (a):
|
|
|
|
sed 's/^[^,]*,[^,]*,[^,]*,[^,]*,/.../'
|
|
^ ^ ^
|
|
| | |_ 3rd field
|
|
| |_______ 2nd field
|
|
|_____________ 1st field
|
|
|
|
# Unix script to delete the second field for case (a)
|
|
sed 's/^\([^,]*\),[^,]*,/\1,,/' file
|
|
|
|
# Unix script to change field 1 to 9999 for case (a)
|
|
sed 's/^[^,]*,/9999,/' file
|
|
|
|
In cases (b) and (c):
|
|
|
|
sed 's/^"[^"]*","[^"]*","[^"]*","[^"]*",/.../'
|
|
1st-- 2nd-- 3rd-- 4th--
|
|
|
|
# Unix script to delete the second field for case (c)
|
|
sed 's/^\("[^"]*"\),"[^"]*",/\1,"",/' file
|
|
|
|
# Unix script to change field 1 to 9999 for case (c)
|
|
sed 's/^"[^"]*",/"9999",/' file
|
|
|
|
|
|
In case (d):
|
|
|
|
One way to parse such files is to replace the 3-character field
|
|
separator "," with an unused character like the tab or vertical
|
|
bar. (Technically, the field separator is only the comma while the
|
|
fields are surrounded by "double quotes", but the net _effect_ is
|
|
that fields are separated by quote-comma-quote, with quote
|
|
characters added to the beginning and end of each record.) Search
|
|
your datafile _first_ to make sure that your character appears
|
|
nowhere in it!
|
|
|
|
sed -n '/|/p' file # search for any instance of '|'
|
|
# if it's not found, we can use the '|' to separate fields
|
|
|
|
Then replace the 3-character field separator and parse as before:
|
|
|
|
# sed script to delete the second field for case (d)
|
|
s/","/|/g; # global change of "," to bar
|
|
s/^\([^|]*\)|[^|]|/\1||/; # delete 2nd field
|
|
s/|/","/g; # global change of bar back to ","
|
|
#---end of script---
|
|
|
|
# sed script to change field 1 to 9999 for case (d)
|
|
# Remember to accommodate leading and trailing quote marks
|
|
s/","/|/g;
|
|
s/^[^|]*|/"9999|/;
|
|
s/|/","/g;
|
|
#---end of script---
|
|
|
|
Note that this technique works only if _each_ and _every_ field is
|
|
surrounded with double quotes, including empty fields.
|
|
|
|
The following solution is for more complex examples of (d), such
|
|
as: not all fields contain "double-quote" marks, or the presence of
|
|
embedded "double-quote" marks within fields, or extraneous
|
|
whitespace around field delimiters. (Thanks to Greg Ubben for this
|
|
script!)
|
|
|
|
# sed script to convert case (d) to bar-delimited records
|
|
s/^ *\(.*[^ ]\) *$/|\1|/;
|
|
s/" *, */"|/g;
|
|
: loop
|
|
s/| *\([^",|][^,|]*\) *, */|\1|/g;
|
|
s/| *, */|\1|/g;
|
|
t loop
|
|
s/ *|/|/g;
|
|
s/| */|/g;
|
|
s/^|\(.*\)|$/\1/;
|
|
#---end of script---
|
|
|
|
For example, it turns this (which is badly-formed but legal):
|
|
|
|
first,"",unquoted ,""this" is, quoted " ,, sub "quote" inside, f", lone " empty:
|
|
|
|
into this:
|
|
|
|
first|""|unquoted|""this" is, quoted "||sub "quote" inside|f"|lone " empty:
|
|
|
|
Note that the script preserves the "double-quote" marks, but
|
|
changes only the commas where they are used as field separators. I
|
|
have used the vertical bar "|" because it's easier to read, but you
|
|
may change this to another field separator if you wish.
|
|
|
|
If your CSV datafile is more complex, it would probably not be
|
|
worth the effort to write it in sed. For such a case, you should
|
|
use Perl with a dedicated CSV module (there are at least two recent
|
|
CSV parsers available from CPAN).
|
|
|
|
4.13. How do I handle fixed-length, columnar data?
|
|
|
|
Sed handles fixed-length fields via \(grouping\) and backreferences
|
|
(\1, \2, \3 ...). If we have 3 fields of 10, 25, and 9 characters
|
|
per field, our sed script might look like so:
|
|
|
|
s/^\(.\{10\}\)\(.\{25\}\)\(.\{9\}\)/\3\2\1/; # Change the fields
|
|
^^^^^^^^^^^~~~~~~~~~~~========== # from 1,2,3 to 3,2,1
|
|
field #1 field #2 field #3
|
|
|
|
This is a bit hard to read. By using GNU sed or ssed with the -r
|
|
switch active, it can look like this:
|
|
|
|
s/^(.{10})(.{25})(.{9})/\3\2\1/; # Using the -r switch
|
|
|
|
To delete a field in sed, use grouping and omit the backreference
|
|
from the field to be deleted. If the data is long or difficult to
|
|
work with, use ssed with the -R switch and the /x flag after an s///
|
|
command, to insert comments and remarks about the fields.
|
|
|
|
For records with many fields, use GNU awk with the FIELDWIDTHS
|
|
variable set in the top of the script. For example:
|
|
|
|
awk 'BEGIN{FIELDWIDTHS = "10 25 9"}; {print $3 $2 $1}' file
|
|
|
|
This is much easier to read than a similar sed script, especially
|
|
if there are more than 5 or 6 fields to manipulate.
|
|
|
|
4.14. How do I commify a string of numbers?
|
|
|
|
Use the simplest script necessary to accomplish your task. As
|
|
variations of the line increase, the sed script must become more
|
|
complex to handle additional conditions. Whole numbers are
|
|
simplest, followed by decimal formats, followed by embedded words.
|
|
|
|
Case 1: simple strings of whole numbers separated by spaces or
|
|
commas, with an optional negative sign. To convert this:
|
|
|
|
4381, -1222333, and 70000: - 44555666 1234567890 words
|
|
56890 -234567, and 89222 -999777 345888777666 chars
|
|
|
|
to this:
|
|
|
|
4,381, -1,222,333, and 70,000: - 44,555,666 1,234,567,890 words
|
|
56,890 -234,567, and 89,222 -999,777 345,888,777,666 chars
|
|
|
|
use one of these one-liners:
|
|
|
|
sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' # GNU sed
|
|
sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' # other seds
|
|
|
|
Case 2: strings of numbers which may have an embedded decimal
|
|
point, separated by spaces or commas, with an optional negative
|
|
sign. To change this:
|
|
|
|
4381, -6555.1212 and 70000, 7.18281828 44906982.071902
|
|
56890 -2345.7778 and 8.0000: -49000000 -1234567.89012
|
|
|
|
to this:
|
|
|
|
4,381, -6,555.1212 and 70,000, 7.18281828 44,906,982.071902
|
|
56,890 -2,345.7778 and 8.0000: -49,000,000 -1,234,567.89012
|
|
|
|
use the following command for GNU sed:
|
|
|
|
sed ':a;s/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g;ta'
|
|
|
|
and for other versions of sed:
|
|
|
|
sed -f case2.sed files
|
|
|
|
# case2.sed
|
|
s/^/ /; # add space to start of line
|
|
:a
|
|
s/\( [-0-9]\{1,\}\)\([0-9]\{3\}\)/\1,\2/g
|
|
ta
|
|
s/ //; # remove space from start of line
|
|
#---end of script---
|
|
|
|
4.15. How do I prevent regex expansion on substitutions?
|
|
|
|
Sometimes you want to *match* regular expression metacharacters as
|
|
literals (e.g., you want to match "[0-9]" or "\n"), to be replaced
|
|
with something else. The ordinary way to prevent expanding
|
|
metacharacters is to prefix them with a backslash. Thus, if "\n"
|
|
matches a newline, "\\n" will match the two-character string of
|
|
'backslash' followed by 'n'.
|
|
|
|
But doing this repeatedly can become tedious if there are many
|
|
regexes. The following script will replace alternating strings of
|
|
literals, where no character is interpreted as a regex
|
|
metacharacter:
|
|
|
|
# filename: sub_quote.sed
|
|
# author: Paolo Bonzini
|
|
# sed script to add backslash to find/replace metacharacters
|
|
N; # add even numbered line to pattern space
|
|
s,[]/\\$*[],\\&,g; # quote all of [, ], /, \, $, or *
|
|
s,^,s/,; # prepend "s/" to front of pattern space
|
|
s,$,/,; # append "/" to end of pattern space
|
|
s,\n,/,; # change "\n" to "/", making s/from/to/
|
|
#---end of script---
|
|
|
|
Here's a sample of how sub_quote.sed might be used. This example
|
|
converts typical sed regexes to perl-style regexes. The input file
|
|
consists of 10 lines:
|
|
|
|
[0-9]
|
|
\d
|
|
[^0-9]
|
|
\D
|
|
\+
|
|
+
|
|
\?
|
|
?
|
|
\|
|
|
|
|
|
|
|
Run the command "sed -f sub_quote.sed input", to transform the
|
|
input file (above) to 5 lines of output:
|
|
|
|
s/\[0-9\]/\\d/
|
|
s/\[^0-9\]/\\D/
|
|
s/\\+/+/
|
|
s/\\?/?/
|
|
s/\\|/|/
|
|
|
|
The above file is itself a sed script, which can then be used to
|
|
modify other files.
|
|
|
|
4.16. How do I convert a string to all lowercase or capital letters?
|
|
|
|
The easiest method is to use a new version of GNU sed, ssed, sedmod
|
|
or sed16 and employ the \U, \L, or other switches on the right side
|
|
of an s/// command. For example, to convert any word which begins
|
|
with "reg" or "exp" into solid capital letters:
|
|
|
|
sed -r "s/\<(reg|exp)[a-z]+/\U&/g" # gsed4.+ or ssed
|
|
sed "s/\<reg[a-z]+/\U&/g; s/\<exp[a-z]+/\U&/g" # sed16 and sedmod
|
|
|
|
As you can see, sedmod and sed16 do not support alternation (|),
|
|
but they do support case conversion. If none of these versions of
|
|
sed are available to you, some sample scripts for this task are
|
|
available from the Seder's Grab Bag:
|
|
|
|
http://sed.sourceforge.net/grabbag/scripts
|
|
|
|
Note that some case conversion scripts are listed under "Filename
|
|
manipulation" and others are under "Text formatting."
|
|
|
|
CHANGING BLOCKS (consecutive lines)
|
|
|
|
4.20. How do I change only one section of a file?
|
|
|
|
You can match a range of lines by line number, by regexes (say, all
|
|
lines between the words "from" and "until"), or by a combination of
|
|
the two. For multiple substitutions on the same range, put the
|
|
command(s) between braces {...}. For example:
|
|
|
|
# replace only between lines 1 and 20
|
|
1,20 s/Johnson/White/g
|
|
|
|
# replace everywhere EXCEPT between lines 1 and 20
|
|
1,20 !s/Johnson/White/g
|
|
|
|
# replace only between words "from" and "until". Note the
|
|
# use of \<....\> as word boundary markers in GNU sed.
|
|
/from/,/until/ { s/\<red\>/magenta/g; s/\<blue\>/cyan/g; }
|
|
|
|
# replace only from the words "ENDNOTES:" to the end of file
|
|
/ENDNOTES:/,$ { s/Schaff/Herzog/g; s/Kraft/Ebbing/g; }
|
|
|
|
For technical details on using address ranges, see section 3.3
|
|
("Addressing and Address ranges").
|
|
|
|
4.21. How do I delete or change a block of text if the block contains
|
|
a certain regular expression?
|
|
|
|
The following deletes the block between 'start' and 'end'
|
|
inclusively, if and only if the block contains the string
|
|
'regex'. Written by Russell Davies, with additional comments:
|
|
|
|
# sed script to delete a block if /regex/ matches inside it
|
|
:t
|
|
/start/,/end/ { # For each line between these block markers..
|
|
/end/!{ # If we are not at the /end/ marker
|
|
$!{ # nor the last line of the file,
|
|
N; # add the Next line to the pattern space
|
|
bt
|
|
} # and branch (loop back) to the :t label.
|
|
} # This line matches the /end/ marker.
|
|
/regex/d; # If /regex/ matches, delete the block.
|
|
} # Otherwise, the block will be printed.
|
|
#---end of script---
|
|
|
|
Note: When the script above reaches /regex/, the entire multi-line
|
|
block is in the pattern space. To replace items inside the block,
|
|
use "s///". To change the entire block, use the 'c' (change)
|
|
command:
|
|
|
|
/regex/c\
|
|
1: This will replace the entire block\
|
|
2: with these two lines of text.
|
|
|
|
4.22. How do I locate a paragraph of text if the paragraph contains a
|
|
certain regular expression?
|
|
|
|
Assume that paragraphs are separated by blank lines. For regexes
|
|
that are single terms, use one of the following scripts:
|
|
|
|
sed -e '/./{H;$!d;}' -e 'x;/regex/!d' # most seds
|
|
sed '/./{H;$!d;};x;/regex/!d' # GNU sed
|
|
|
|
To print paragraphs only if they contain 3 specific regular
|
|
expressions (RE1, RE2, and RE3), in any order in the paragraph:
|
|
|
|
sed -e '/./{H;$!d;}' -e 'x;/RE1/!d;/RE2/!d;/RE3/!d'
|
|
|
|
With this solution and the preceding one, if the paragraphs are
|
|
excessively long (more than 4k in length), you may overflow sed's
|
|
internal buffers. If using HHsed, you must add a "G;" command
|
|
immediately after the "x;" in the scripts above to defeat a bug
|
|
in HHsed (see section 7.9(5), below, for a description).
|
|
|
|
4.23. How do I match a block of _specific_ consecutive lines?
|
|
|
|
There are three ways to approach this problem:
|
|
|
|
(1) Try to use a "/range/, /expression/"
|
|
(2) Try to use a "/multi-line\nexpression/"
|
|
(3) Try to use a block of "literal strings"
|
|
|
|
We describe each approach in the following sections.
|
|
|
|
4.23.1. Try to use a "/range/, /expression/"
|
|
|
|
If the block of lines are strings that *never change their order*
|
|
and if the top line never occurs outside the block, like this:
|
|
|
|
Abel
|
|
Baker
|
|
Charlie
|
|
Delta
|
|
|
|
then these solutions will work for deleting the block:
|
|
|
|
sed 's/^Abel$/{N;N;N;d;}' files # for blocks with few lines
|
|
sed '/^Abel$/, /^Zebra$/d' files # for blocks with many lines
|
|
sed '/^Abel$/,+25d' files # HHsed, sedmod, ssed, gsed 3.02.80
|
|
|
|
To change the block, use the 'c' (change) command instead of 'd'.
|
|
To print that block only, use the -n switch and 'p' (print) instead
|
|
of 'd'. To change some things inside the block, try this:
|
|
|
|
/^Abel$/,/^Delta$/ {
|
|
:ack
|
|
N;
|
|
/\nDelta$/! b ack
|
|
# At this point, all the lines in the block are collected
|
|
s/ubstitute /somethin/g;
|
|
}
|
|
|
|
4.23.2. Try to use a "multi-line\nexpression"
|
|
|
|
If the top line of the block sometimes appears alone or is
|
|
sometimes followed by other lines, or if a partial block may occur
|
|
somewhere in the file, a multi-line expression may be required.
|
|
|
|
In these examples, we give solutions for matching an N-line block.
|
|
The expression "/^RE1\nRE2\nRE3...$/" represents a properly formed
|
|
regular expression where \n indicates a newline between lines. Note
|
|
that the 'N' followed by the 'P;D;' commands forms a "sliding
|
|
window" technique. A window of N lines is formed. If the multi-line
|
|
pattern matches, the block is handled. If not, the top line is
|
|
printed and then deleted from the pattern space, and we try to
|
|
match at the next line.
|
|
|
|
# sed script to delete 2 consecutive lines: /^RE1\nRE2$/
|
|
$b
|
|
/^RE1$/ {
|
|
$!N
|
|
/^RE1\nRE2$/d
|
|
P;D
|
|
}
|
|
#---end of script---
|
|
|
|
# sed script to delete 3 consecutive lines. (This script
|
|
# fails under GNU sed v2.05 and earlier because of the 't'
|
|
# bug when s///n is used; see section 7.5(1) of the FAQ.)
|
|
: more
|
|
$!N
|
|
s/\n/&/2;
|
|
t enough
|
|
$!b more
|
|
: enough
|
|
/^RE1\nRE2\nRE3$/d
|
|
P;D
|
|
#---end of script---
|
|
|
|
For example, to delete a block of 5 consecutive lines, the previous
|
|
script must be altered in only two places:
|
|
|
|
(1) Change the 2 in "s/\n/&/2;" to a 4 (the trailing semicolon is
|
|
needed to work around a bug in HHsed v1.5).
|
|
|
|
(2) Change the regex line to "/^RE1\nRE2\nRE3\nRE4\nRE5$/d",
|
|
modifying the expression as needed.
|
|
|
|
Suppose we want to delete a block of two blank lines followed by
|
|
the word "foo" followed by another blank line (4 lines in all).
|
|
Other blank lines and other instances of "foo" should be left
|
|
alone. After changing the '2' to a '3' (always one number less than
|
|
the total number of lines), the regex line would look like this:
|
|
"/^\n\nfoo\n$/d". (Thanks to Greg Ubben for this script.)
|
|
|
|
As an alternative to work around the 't' bug in older versions of
|
|
GNU sed, the following script will delete 4 consecutive lines:
|
|
|
|
# sed script to delete 4 consecutive lines. Use this if you
|
|
# require GNU sed 2.05 and below.
|
|
/^RE1$/!b
|
|
$!N
|
|
$!N
|
|
:a
|
|
$b
|
|
N
|
|
/^RE1\nRE2\nRE3\nRE4$/d
|
|
P
|
|
s/^.*\n\(.*\n.*\n.*\)$/\1/
|
|
ba
|
|
#---end of script---
|
|
|
|
Its drawback is that it must be modified in 3 places instead of 2
|
|
to adapt it for more lines, and as additional lines are added, the
|
|
's' command is forced to work harder to match the regexes. On the
|
|
other hand, it avoids a bug with gsed-2.05 and illustrates another
|
|
way to solve the problem of deleting consecutive lines.
|
|
|
|
4.23.3. Try to use a block of "literal strings"
|
|
|
|
If you need to match a static block of text (which may occur any
|
|
number of times throughout a file), where the contents of the block
|
|
are known in advance, then this script is easy to use. It requires
|
|
an intermediate file, which we will call "findrep.txt" (below):
|
|
|
|
A block of several consecutive lines to
|
|
be matched literally should be placed on
|
|
top. Regular expressions like .* or [a-z]
|
|
will lose their special meaning and be
|
|
interpreted literally in this block.
|
|
----
|
|
Four hyphens separate the two sections. Put
|
|
the replacement text in the lower section.
|
|
As above, sed symbols like &, \n, or \1 will
|
|
lose their special meaning.
|
|
|
|
This is a 3-step process. A generic script called "blockrep.sed"
|
|
will read "findrep.txt" (above) and generate a custom script, which
|
|
is then used on the actual input file. In other words,
|
|
"findrep.txt" is a simplified description of the editing that you
|
|
want to do on the block, and "blockrep.sed" turns it into actual
|
|
sed commands.
|
|
|
|
Use this process from a Unix shell or from a DOS prompt:
|
|
|
|
sed -nf blockrep.sed findrep.txt >custom.sed
|
|
sed -f custom.sed input.file >output.file
|
|
erase custom.sed
|
|
|
|
The generic script "blockrep.sed" follows below. It's fairly long.
|
|
Examining its output might help you understanding how to use the
|
|
_sliding window_ technique.
|
|
|
|
# filename: blockrep.sed
|
|
# author: Paolo Bonzini
|
|
# Requires:
|
|
# (1) blocks to find and replace, e.g., findrep.txt
|
|
# (2) an input file to be changed, input.file
|
|
#
|
|
# blockrep.sed creates a second sed script, custom.sed,
|
|
# to find the lines above the row of 4 hyphens, globally
|
|
# replacing them with the lower block of text. GNU sed
|
|
# is recommended but not required for this script.
|
|
#
|
|
# Loop on the first part, accumulating the `from' text
|
|
# into the hold space.
|
|
:a
|
|
/^----$/! {
|
|
# Escape slashes, backslashes, the final newline and
|
|
# regular expression metacharacters.
|
|
s,[/\[.*],\\&,g
|
|
s/$/\\/
|
|
H
|
|
#
|
|
# Append N cmds needed to maintain the sliding window.
|
|
x
|
|
1 s,^.,s/,
|
|
1! s/^/N\
|
|
/
|
|
x
|
|
n
|
|
ba
|
|
}
|
|
#
|
|
# Change the final backslash to a slash to separate the
|
|
# two sides of the s command.
|
|
x
|
|
s,\\$,/,
|
|
x
|
|
#
|
|
# Until EOF, gather the substitution into hold space.
|
|
:b
|
|
n
|
|
s,[/\],\\&,g
|
|
$! s/$/\\/
|
|
H
|
|
$! bb
|
|
#
|
|
# Start the RHS of the s command without a leading
|
|
# newline, add the P/D pair for the sliding window, and
|
|
# print the script.
|
|
g
|
|
s,/\n,/,
|
|
s,$,/\
|
|
P\
|
|
D,p
|
|
#---end of script---
|
|
|
|
4.24. How do I address all the lines between RE1 and RE2, excluding the
|
|
lines themselves?
|
|
|
|
Normally, to address the lines between two regular expressions, RE1
|
|
and RE2, one would do this: '/RE1/,/RE2/{commands;}'. Excluding
|
|
those lines takes an extra step. To put 2 arrows before each line
|
|
between RE1 and RE2, except for those lines:
|
|
|
|
sed '1,/RE1/!{ /RE2/,/RE1/!s/^/>>/; }' input.fil
|
|
|
|
The preceding script, though short, may be difficult to follow. It
|
|
also requires that /RE1/ cannot occur on the first line of the
|
|
input file. The following script, though it's not a one-liner, is
|
|
easier to read and it permits /RE1/ to appear on the first line:
|
|
|
|
# sed script to replace all lines between /RE1/ and /RE2/,
|
|
# without matching /RE1/ or /RE2/
|
|
/RE1/,/RE2/{
|
|
/RE1/b
|
|
/RE2/b
|
|
s/^/>>/
|
|
}
|
|
#---end of script---
|
|
|
|
Contents of input.fil: Output of sed script:
|
|
aaa aaa
|
|
bbb bbb
|
|
RE1 RE1
|
|
aaa >>aaa
|
|
bbb >>bbb
|
|
ccc >>ccc
|
|
RE2 RE2
|
|
end end
|
|
|
|
4.25. How do I join two lines if line #1 ends in a [certain string]?
|
|
|
|
This question appears in the section on one-line sed scripts, but
|
|
it comes up so many times that it needs a place here also. Suppose
|
|
a line ends with a particular string (often, a line ends with a
|
|
backslash). How do you bring up the second line after it, even in
|
|
cases where several consecutive lines all end in a backslash?
|
|
|
|
sed -e :a -e '/\\$/N; s/\\\n//; ta' file # all seds
|
|
sed ':a; /\\$/N; s/\\\n//; ta' file # GNU sed, ssed, HHsed
|
|
|
|
Note that this replaces the backslash-newline with nothing. You may
|
|
want to replace the backslash-newline with a single space instead.
|
|
|
|
4.26. How do I join two lines if line #2 begins in a [certain string]?
|
|
|
|
The inverse situation is another FAQ. Suppose a line begins with a
|
|
particular string. How do you bring that line up to follow the
|
|
previous line? In this example, we want to match the string "<<="
|
|
at the beginning of one line, bring that line up to the end of the
|
|
line before it, and replace the string with a single space:
|
|
|
|
sed -e :a -e '$!N;s/\n<<=/ /;ta' -e 'P;D' file # all seds
|
|
sed ':a; $!N;s/\n<<=/ /;ta;P;D' file # GNU, ssed, sed15+
|
|
|
|
4.27. How do I change all paragraphs to long lines?
|
|
|
|
A frequent request is how to convert DOS-style textfiles, in which
|
|
each line ends with "paragraph marker", to Microsoft-style
|
|
textfiles, in which the "paragraph" marker only appears at the end
|
|
of real paragraphs. Sometimes this question is framed as, "How do I
|
|
remove the hard returns at the end of each line in a paragraph?"
|
|
|
|
The problem occurs because newer word processors don't work the
|
|
same way older text editors did. Older text editors used a newline
|
|
(CR/LF in DOS; LF alone in Unix) to end each line on screen or on
|
|
disk, and used two newlines to separate paragraphs. Certain word
|
|
processors wanted to make paragraph reformatting and reflowing work
|
|
easily, so they use one newline to end a paragraph and never allow
|
|
newlines _within_ a paragraph. This means that textfiles created
|
|
with standard editors (Emacs, vi, Vedit, Boxer, etc.) appear to
|
|
have "hard returns" at inappropriate places. The following sed
|
|
script finds blocks of consecutive nonblank lines (i.e., paragraphs
|
|
of text), and converts each block into one long line with one "hard
|
|
return" at the end.
|
|
|
|
# sed script to change all paragraphs to long lines
|
|
/./{H; $!d;} # Put each paragraph into hold space
|
|
x; # Swap hold space and pattern space
|
|
s/^\(\n\)\(..*\)$/\2\1/; # Move leading \n to end of PatSpace
|
|
s/\n\(.\)/ \1/g; # Replace all other \n with 1 space
|
|
# Uncomment the following line to remove excess blank lines:
|
|
# /./!d;
|
|
#---end of sed script---
|
|
|
|
If the input files have formatting or indentation that conveys
|
|
special meaning (like program source code), this script will remove
|
|
it. But if the text still needs to be extended, try 'par'
|
|
(paragraph reformatter) or the 'fmt' utility with the -t or -c
|
|
switches and the width option (-w) set to a number like 9999.
|
|
|
|
SHELL AND ENVIRONMENT
|
|
|
|
4.30. How do I read environment variables with sed?
|
|
|
|
4.30.1. - on Unix platforms
|
|
|
|
In Unix, environment variables begin with a dollar sign, such as
|
|
$TERM, $PATH, $var or $i. In sed, the dollar sign is used to
|
|
indicate the last line of the input file, the end of a line (in the
|
|
LHS), or a literal symbol (in the RHS). Sed cannot access variables
|
|
directly, so one must pay attention to shell quoting requirements
|
|
to expand the variables properly.
|
|
|
|
To ALLOW the Unix shell to interpret the dollar sign, put the
|
|
script in double quotes:
|
|
|
|
sed "s/_terminal-type_/$TERM/g" input.file >output.file
|
|
|
|
To PREVENT the Unix shell from interpreting the dollar sign as a
|
|
shell variable, put the script in single quotes:
|
|
|
|
sed 's/.$//' infile >outfile
|
|
|
|
To use BOTH Unix $environment_vars and sed /end-of-line$/ pattern
|
|
matching, there are two solutions. (1) The easiest is to enclose
|
|
the script in "double quotes" so the shell can see the $variables,
|
|
and to prefix the sed metacharacter ($) with a backslash. Thus, in
|
|
|
|
sed "s/$user\$/root/" file
|
|
|
|
the shell interpolates $user and sed interprets \$ as the symbol
|
|
for end-of-line.
|
|
|
|
(2) Another method--somewhat less readable--is to concatenate the
|
|
script with 'single quotes' where the $ should not be interpolated
|
|
and "double quotes" where variable interpolation should occur. To
|
|
demonstrate using the preceding script:
|
|
|
|
sed "s/$user"'$/root/' file
|
|
|
|
Solution #1 seems easier to remember. In either case, we search for
|
|
the user's name (stored in a variable called $user) when it occurs
|
|
at the end of the line ($), and substitute the word "root" in all
|
|
matches.
|
|
|
|
For longer shell scripts, it is sometimes useful to begin with
|
|
single quote marks ('), close them upon encountering the variable,
|
|
enclose the variable name in double quotes ("), and resume with
|
|
single quotes, closing them at the end of the sed script. Example:
|
|
|
|
#! /bin/sh
|
|
# sed script to illustrate 'quote'"matching"'usage'
|
|
FROM='abcdefgh'
|
|
TO='ABCDEFGH'
|
|
sed -e '
|
|
y/'"$FROM"'/'"$TO"'/; # note the quote pairing
|
|
# some more commands go here . . .
|
|
# last line is a single quote mark
|
|
'
|
|
|
|
Thus, each variable named $FROM is replaced by $TO, and the single
|
|
quotes are used to glue the multiple lines together in the script.
|
|
(See also section 4.10, "How do I handle shell quoting in sed?")
|
|
|
|
4.30.2. - on MS-DOS and 4DOS platforms
|
|
|
|
Under 4DOS and MS-DOS version 7.0 (Win95) or 7.10 (Win95 OSR2),
|
|
environment variables can be accessed from the command prompt.
|
|
Under MS-DOS v6.22 and below, environment variables can only be
|
|
accessed from within batch files. Environment variables should be
|
|
enclosed between percent signs and are case-insensitive; i.e.,
|
|
%USER% or %user% will display the USER variable. To generate a true
|
|
percent sign, just enter it twice.
|
|
|
|
DOS versions of sed require that sed scripts be enclosed by double
|
|
quote marks "..." (not single quotes!) if the script contains
|
|
embedded tabs, spaces, redirection arrows or the vertical bar. In
|
|
fact, if the input for sed comes from piping, a sed script should
|
|
not contain a vertical bar, even if it is protected by double
|
|
quotes (this seems to be bug in the normal MS-DOS syntax). Thus,
|
|
|
|
echo blurk | sed "s/^/ |foo /" # will cause an error
|
|
sed "s/^/ |foo /" blurk.txt # will work as expected
|
|
|
|
Using DOS environment variables which contain DOS path statements
|
|
(such as a TMP variable set to "C:\TEMP") within sed scripts is
|
|
discouraged because sed will interpret the backslash '\' as a
|
|
metacharacter to "quote" the next character, not as a normal
|
|
symbol. Thus,
|
|
|
|
sed "s/^/%TMP% /" somefile.txt
|
|
|
|
will not prefix each line with (say) "C:\TEMP ", but will prefix
|
|
each line with "C:TEMP "; sed will discard the backslash, which is
|
|
probably not what you want. Other variables such as %PATH% and
|
|
%COMSPEC% will also lose the backslash within sed scripts.
|
|
|
|
Environment variables which do not use backslashes are usually
|
|
workable. Thus, all the following should work without difficulty,
|
|
if they are invoked from within DOS batch files:
|
|
|
|
sed "s/=username=/%USER%/g" somefile.txt
|
|
echo %FILENAME% | sed "s/\.TXT/.BAK/"
|
|
grep -Ei "%string%" somefile.txt | sed "s/^/ /"
|
|
|
|
while from either the DOS prompt or from within a batch file,
|
|
|
|
sed "s/%%/ percent/g" input.fil >output.fil
|
|
|
|
will replace each percent symbol in a file with " percent" (adding
|
|
the leading space for readability).
|
|
|
|
4.31. How do I export or pass variables back into the environment?
|
|
|
|
4.31.1. - on Unix platforms
|
|
|
|
Suppose that line #1, word #2 of the file 'terminals' contains a
|
|
value to be put in your TERM environment variable. Sed cannot
|
|
export variables directly to the shell, but it can pass strings to
|
|
shell commands. To set a variable in the Bourne shell:
|
|
|
|
TERM=`sed 's/^[^ ][^ ]* \([^ ][^ ]*\).*/\1/;q' terminals`;
|
|
export TERM
|
|
|
|
If the second word were "Wyse50", this would send the shell command
|
|
"TERM=Wyse50".
|
|
|
|
4.31.2. - on MS-DOS or 4DOS platforms
|
|
|
|
Sed cannot directly manipulate the environment. Under DOS, only
|
|
batch files (.BAT) can do this, using the SET instruction, since
|
|
they are run directly by the command shell. Under 4DOS, special
|
|
4DOS commands (such as ESET) can also alter the environment.
|
|
|
|
Under DOS or 4DOS, sed can select a word and pass it to the SET
|
|
command. Suppose you want the 1st word of the 2nd line of MY.DAT
|
|
put into an environment variable named %PHONE%. You might do this:
|
|
|
|
@echo off
|
|
sed -n "2 s/^\([^ ][^ ]*\) .*/SET PHONE=\1/p;3q" MY.DAT > GO_.BAT
|
|
call GO_.BAT
|
|
echo The environment variable for PHONE is %PHONE%
|
|
:: cleanup
|
|
del GO_.BAT
|
|
|
|
The sed script assumes that the first character on the 2nd line is
|
|
not a space and uses grouping \(...\) to save the first string of
|
|
non-space characters as \1 for the RHS. In writing any batch files,
|
|
make sure that output filenames such as GO_.BAT don't overwrite
|
|
preexisting files of the same name.
|
|
|
|
4.32. How do I handle Unix shell quoting in sed?
|
|
|
|
To embed a literal single quote (') in a script, use (a) or (b):
|
|
|
|
(a) If possible, put the script in double quotes:
|
|
|
|
sed "s/cannot/can't/g" file
|
|
|
|
(b) If the script must use single quotes, then close-single-quote
|
|
the script just before the SPECIAL single quote, prefix the single
|
|
quote with a backslash, and use a 2nd pair of single quotes to
|
|
finish marking the script. Thus:
|
|
|
|
sed 's/cannot$/can'\''t/g' file
|
|
|
|
Though this looks hard to read, it breaks down to 3 parts:
|
|
|
|
's/cannot$/can' \' 't/g'
|
|
--------------- -- -----
|
|
|
|
To embed a literal double quote (") in a script, use (a) or (b):
|
|
|
|
(a) If possible, put the script in single quotes. You don't need to
|
|
prefix the double quotes with anything. Thus:
|
|
|
|
sed 's/14"/fourteen inches/g' file
|
|
|
|
(b) If the script must use double quotes, then prefix the SPECIAL
|
|
double quote with a backslash (\). Thus,
|
|
|
|
sed "s/$length\"/$length inches/g" file
|
|
|
|
To embed a literal backslash (\) into a script, enter it twice:
|
|
|
|
sed 's/C:\\DOS/D:\\DOS/g' config.sys
|
|
|
|
FILES, DIRECTORIES, AND PATHS
|
|
|
|
4.40. How do I read (insert/add) a file at the top of a textfile?
|
|
|
|
Normally, adding a "header" file to the top of a "body" file is
|
|
done from the command prompt before passing the file on to sed.
|
|
(MS-DOS below version 6.0 must use COPY and DEL instead of MOVE in
|
|
the following example.)
|
|
|
|
copy header.txt+body temp # MS-DOS command 1
|
|
echo Y | move temp body # MS-DOS command 2
|
|
#
|
|
cat header.txt body >temp; mv temp body # Unix commands
|
|
|
|
However, if inserting the file must occur within sed, there is a
|
|
way. The sed command "1 r header.txt" will not work; it will print
|
|
line 1 and then insert "header.txt" between lines 1 and 2. The
|
|
following script solves this problem; however, there must be at
|
|
least 2 lines in the target file for the script to work properly.
|
|
|
|
# sed script to insert "header.txt" above the first line
|
|
1{h; r header.txt
|
|
D; }
|
|
2{x; G; }
|
|
#---end of sed script---
|
|
|
|
4.41. How do I make substitutions in every file in a directory, or in
|
|
a complete directory tree?
|
|
|
|
4.41.1. - ssed and Perl solution
|
|
|
|
The best solution for multiple files in a single directory is to
|
|
use ssed or gsed v4.0 or higher:
|
|
|
|
sed -i.BAK 's|foo|bar|g' files # -i does in-place replacement
|
|
|
|
If you don't have ssed, there is a similar solution in Perl. (Yes,
|
|
we know this is a FAQ file for sed, not perl, but perl is more
|
|
common than ssed for many users.)
|
|
|
|
perl -pi.bak -e 's|foo|bar|g' files # or
|
|
perl -pi.bak -e 's|foo|bar|g' `find /pathname -name "filespec"`
|
|
|
|
For each file in the filelist, sed (or Perl) renames the source
|
|
file to "filename.bak"; the modified file gets the original
|
|
filename. Remove '.bak' if you don't need backup copies. (Note the
|
|
use of "s|||" instead of "s///" here, and in the scripts below. The
|
|
vertical bars in the 's' command let you replace '/some/path' with
|
|
'/another/path', accommodating slashes in the LHS and RHS.)
|
|
|
|
To recurse directories in Unix or GNU/Linux:
|
|
|
|
# We use xargs to prevent passing too many filenames to sed, but
|
|
# this command will fail if filenames contain spaces or newlines.
|
|
find /my/path -name '*.ht' -print | xargs sed -i.BAK 's|foo|bar|g'
|
|
|
|
To recurse directories under Windows 2000 (CMD.EXE or COMMAND.COM):
|
|
|
|
# This syntax isn't supported under Windows 9x COMMAND.COM
|
|
for /R c:\my\path %f in (*.htm) do sed -i.BAK "s|foo|bar|g" %f
|
|
|
|
4.41.2. - Unix solution
|
|
|
|
For all files in a single directory, assuming they end with *.txt
|
|
and you have no files named "[anything].txt.bak" already, use a
|
|
shell script:
|
|
|
|
#! /bin/sh
|
|
# Source files are saved as "filename.txt.bak" in case of error
|
|
# The '&&' after cp is an additional safety feature
|
|
for file in *.txt
|
|
do
|
|
cp $file $file.bak &&
|
|
sed 's|foo|bar|g' $file.bak >$file
|
|
done
|
|
|
|
To do an entire directory tree, use the Unix utility find, like so
|
|
(thanks to Jim Dennis <jadestar@rahul.net> for this script):
|
|
|
|
#! /bin/sh
|
|
# filename: replaceall
|
|
# Backup files are NOT saved in this script.
|
|
find . -type f -name '*.txt' -print | while read i
|
|
do
|
|
sed 's|foo|bar|g' $i > $i.tmp && mv $i.tmp $i
|
|
done
|
|
|
|
This previous shell script recurses through the directory tree,
|
|
finding only files in the directory (not symbolic links, which will
|
|
be encountered by the shell command "for file in *.txt", above). To
|
|
preserve file permissions and make backup copies, use the 2-line cp
|
|
routine of the earlier script instead of "sed ... && mv ...". By
|
|
replacing the sed command 's|foo|bar|g' with something like
|
|
|
|
sed "s|$1|$2|g" ${i}.bak > $i
|
|
|
|
using double quotes instead of single quotes, the user can also
|
|
employ positional parameters on the shell script command tail, thus
|
|
reusing the script from time to time. For example,
|
|
|
|
replaceall East West
|
|
|
|
would modify all your *.txt files in the current directory.
|
|
|
|
4.41.3. - DOS solution:
|
|
|
|
MS-DOS users should use two batch files like this:
|
|
|
|
@echo off
|
|
:: MS-DOS filename: REPLACE.BAT
|
|
::
|
|
:: Create a destination directory to put the new files.
|
|
:: Note: The next command will fail under Novel Netware
|
|
:: below version 4.10 unless "SHOW DOTS=ON" is active.
|
|
if not exist .\NEWFILES\NUL mkdir NEWFILES
|
|
for %%f in (*.txt) do CALL REPL_2.BAT %%f
|
|
echo Done!!
|
|
:: ---End of first batch file---
|
|
|
|
@echo off
|
|
:: MS-DOS filename: REPL_2.BAT
|
|
::
|
|
sed "s/foo/bar/g" %1 > NEWFILES\%1
|
|
:: ---End of the second batch file---
|
|
|
|
When finished, the current directory contains all the original
|
|
files, and the newly-created NEWFILES subdirectory contains the
|
|
modified *.TXT files. Do not attempt a command like
|
|
|
|
for %%f in (*.txt) do sed "s/foo/bar/g" %%f >NEWFILES\%%f
|
|
|
|
under any version of MS-DOS because the output filename will be
|
|
created as a literal '%f' in the NEWFILES directory before the
|
|
%%f is expanded to become each filename in (*.txt). This occurs
|
|
because MS-DOS creates output filenames via redirection commands
|
|
before it expands "for..in..do" variables.
|
|
|
|
To recurse through an entire directory tree in MS-DOS requires a
|
|
batch file more complex than we have room to describe. Examine the
|
|
file SWEEP.BAT in Timo Salmi's great archive of batch tricks,
|
|
located at <ftp://garbo.uwasa.fi/pc/link/tsbat.zip> (this file is
|
|
regularly updated). Another alternative is to get an external
|
|
program designed for directory recursion. Here are some recommended
|
|
programs for directory recursion. The first one, FORALL, runs under
|
|
either OS/2 or DOS. Unfortunately, none of these supports Win9x
|
|
long filenames.
|
|
|
|
http://hobbes.nmsu.edu/pub/os2/util/disk/forall72.zip
|
|
ftp://garbo.uwasa.fi/pc/filefind/target15.zip
|
|
|
|
4.42. How do I replace "/some/UNIX/path" in a substitution?
|
|
|
|
Technically, the normal meaning of the slash can be disabled by
|
|
prefixing it with a backslash. Thus,
|
|
|
|
sed 's/\/some\/UNIX\/path/\/a\/new\/path/g' files
|
|
|
|
But this is hard to read and write. There is a better solution.
|
|
The s/// substitution command allows '/' to be replaced by any
|
|
other character (including spaces or alphanumerics). Thus,
|
|
|
|
sed 's|/some/UNIX/path|/a/new/path|g' files
|
|
|
|
and if you are using variable names in a Unix shell script,
|
|
|
|
sed "s|$OLDPATH|$NEWPATH|g" oldfile >newfile
|
|
|
|
4.43. How do I replace "C:\SOME\DOS\PATH" in a substitution?
|
|
|
|
For MS-DOS users, every backslash must be doubled. Thus, to replace
|
|
"C:\SOME\DOS\PATH" with "D:\MY\NEW\PATH":
|
|
|
|
sed "s|C:\\SOME\\DOS\\PATH|D:\\MY\\NEW\\PATH|g" infile >outfile
|
|
|
|
Remember that DOS pathnames are not case sensitive and can appear
|
|
in upper or lower case in the input file. If this concerns you, use
|
|
a version of sed which can ignore case when matching (gsed, ssed,
|
|
sedmod, sed16).
|
|
|
|
@echo off
|
|
:: sample MS-DOS batch file to alter path statements
|
|
:: requires GNU sed with the /i flag for s///
|
|
set old=C:\\SOME\\DOS\\PATH
|
|
set new=D:\\MY\\NEW\\PATH
|
|
gsed "s|%old%|%new%|gi" infile >outfile
|
|
:: or
|
|
:: sedmod -i "s|%old%|%new%|g" infile >outfile
|
|
set old=
|
|
set new=
|
|
|
|
Also, remember that under Windows long filenames may be stored in
|
|
two formats: e.g., as "C:\Program Files" or as "C:\PROGRA~1".
|
|
|
|
4.44. How do I emulate file-includes, using sed?
|
|
|
|
Given an input file with file-include statements, similar to
|
|
C-style includes or "server-side includes" (SSI) of this format:
|
|
|
|
This is the source file. It's short.
|
|
Its name is simply 'source'. See the script below.
|
|
<!--#include file="ashe.inc"-->
|
|
And this is any amount of text between
|
|
<!--#include file="jesse.inc"-->
|
|
This is the last line of the file.
|
|
|
|
How do we direct sed to import/insert whichever files are at the
|
|
point of the 'file="filename"' token? First, use this file:
|
|
|
|
#n
|
|
# filename: incl.sed
|
|
# Comments supported by GNU sed or ssed. Leading '#n' should
|
|
# be on line 1, columns 1-2 of the line.
|
|
/<!--#include file="/ { # For each "include file" command,
|
|
=; # print the line number
|
|
s/^[^"]*"/{r /; # change pattern to 'r{ '
|
|
s/".*//p; # delete rest to EOL, print
|
|
# and a(ppend) a delete command
|
|
a\
|
|
d;}
|
|
}
|
|
#---end of sed script---
|
|
|
|
Second, use the following shell script or DOS batch file (if
|
|
running a DOS batch file, use "double quotes" instead of 'single
|
|
quotes', and use "del" instead of "rm" to remove the temp file):
|
|
|
|
sed -nf incl.sed source | sed 'N;N;s/\n//' >temp.sed
|
|
sed -f temp.sed source >target
|
|
rm temp.sed
|
|
|
|
If you have GNU sed or ssed, you can reduce the script even further
|
|
(thanks to Michael Carmack for the reminder):
|
|
|
|
sed -nf incl.sed source | sed 'N;N;s/\n//' | sed -f - source >target
|
|
|
|
In brief, the script replaces each filename with a 'r filename'
|
|
command to insert the file at that point, while omitting the
|
|
extraneous material. Two important things to note with this script:
|
|
(1) There should be only one '#include file' directive per line, and
|
|
(2) each '#include file' directive must be the *only* thing on that
|
|
line, because everything else on the line will be deleted.
|
|
|
|
Though the script uses GNU sed or ssed because of the great support
|
|
for embedded script comments, it should run on any version of sed.
|
|
If not, write me and let me know.
|
|
|
|
------------------------------
|
|
|
|
5. WHY ISN'T THIS WORKING?
|
|
|
|
5.1. Why don't my variables like $var get expanded in my sed script?
|
|
|
|
Because your sed script uses 'single quotes' instead of "double
|
|
quotes." Unix shells never expand $variables in single quotes.
|
|
|
|
This is probably the most frequently-asked sed question. For more
|
|
info on using variables, see section 4.30.
|
|
|
|
5.2. I'm using 'p' to print, but I have duplicate lines sometimes.
|
|
|
|
Sed prints the entire file by default, so the 'p' command might
|
|
cause the duplicate lines. If you want the whole file printed,
|
|
try removing the 'p' from commands like 's/foo/bar/p'. If you want
|
|
part of the file printed, run your sed script with -n flag to
|
|
suppress normal output, and rewrite the script to get all output
|
|
from the 'p' comand.
|
|
|
|
If you're still getting duplicate lines, you are probably finding
|
|
several matches for the same line. Suppose you want to print lines
|
|
with the words "Peter" or "James" or "John", but not the same line
|
|
twice. The following command will fail:
|
|
|
|
sed -n '/Peter/p; /James/p; /John/p' files
|
|
|
|
Since all 3 commands of the script are executed for each line,
|
|
you'll get extra lines. A better way is to use the 'd' (delete) or
|
|
'b' (branch) commands, like so (with GNU sed):
|
|
|
|
sed '/Peter/b; /James/b; /John/b; d' files # one way
|
|
sed -n '/Peter/{p;d;};/James/{p;d;};/John/p' files # a 2nd way
|
|
sed -n '/Peter/{p;b;};/James/{p;b;};/John/p' files # a 3rd way
|
|
sed '/Peter\|James\|John/!d' files # shortest way
|
|
|
|
On standard seds, these must be broken down with -e commands:
|
|
|
|
sed -e '/Peter/b' -e '/James/b' -e '/John/b' -e d files
|
|
sed -n -e '/Peter/{p;d;}' -e '/James/{p;d;}' -e '/John/p' files
|
|
|
|
The 3rd line would require too many -e commands to fit on one line,
|
|
since standard versions of sed require an -e command after each 'b'
|
|
and also after each closing brace '}'.
|
|
|
|
5.3. Why does my DOS version of sed process a file part-way through
|
|
and then quit?
|
|
|
|
First, look for errors in the script. Have you used the -n switch
|
|
without telling sed to print anything to the console? Have you read
|
|
the docs to your version of sed to see if it has a syntax you may
|
|
have misused? (Look for an N or H command that gathers too much.)
|
|
|
|
Next, if you are sure your sed script is valid, a probable cause is
|
|
an end-of-file marker embedded in the file. An EOF marker (SUB) is
|
|
a Control-Z character, with the value of 1A hex (26 decimal). As
|
|
soon as any DOS version of sed encounters a Ctrl-Z character, sed
|
|
stops processing.
|
|
|
|
To locate the EOF character, use Vern Buerg's shareware file viewer
|
|
LIST.COM <http://www.buerg.com/list.html>. In text mode, look for a
|
|
right-arrow symbol; in hex mode (Alt-H), look for a 1A code. With
|
|
Unix utilities ported to DOS, use 'od' (octal dump) to display
|
|
hexcodes in your file, and then use sed to locate the offending
|
|
character:
|
|
|
|
od -txC badfile.txt | sed -n "/ 1a /p; / 1a$/p"
|
|
|
|
Then edit the input file to remove the offending character(s).
|
|
|
|
If you would rather NOT edit the input file, there is still a fix.
|
|
It requires the DJGPP 32-bit port of 'tr', the Unix translate
|
|
program (v1.22 or higher). GNU od and tr are currently at v2.0 (for
|
|
DOS); they are packaged with the GNU text utilities, available at
|
|
|
|
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/txt20b.zip
|
|
http://www.simtel.net/gnudlpage.php?product=/gnu/djgpp/v2gnu/txt20b.zip&name=txt20b.zip
|
|
|
|
It is important to get the DJGPP version of 'tr' because other
|
|
versions ported to DOS will stop processing when they encounter the
|
|
EOF character. Use the -d (delete) command:
|
|
|
|
tr -d \32 < badfile.txt | sed -f myscript.sed
|
|
|
|
5.4. My RE isn't matching/deleting what I want it to. (Or, "Greedy vs.
|
|
stingy pattern matching")
|
|
|
|
The two most common causes for this problem are: (1) misusing the
|
|
'.' metacharacter, and (2) misusing the '*' metacharacter. The RE
|
|
'.*' is designed to be "greedy" (i.e., matching as many characters
|
|
as possible). However, sometimes users need an expression which is
|
|
"stingy," matching the shortest possible string.
|
|
|
|
(1) On single-line patterns, the '.' metacharacter matches any
|
|
single character on the line. ('.' cannot match the newline at the
|
|
end of the line because the newline is removed when the line is put
|
|
into the pattern space; sed adds a newline automatically when the
|
|
pattern space is printed.) On multi-line patterns obtained with the
|
|
'N' or 'G' commands, '.' _will_ match a newline in the middle of the
|
|
pattern space. If there are 3 lines in the pattern space, "s/.*//"
|
|
will delete all 3 lines, not just the first one (leaving 1 blank
|
|
line, since the trailing newline is added to the output).
|
|
|
|
Normal misuse of '.' occurs in trying to match a word or bounded
|
|
field, and forgetting that '.' will also cross the field limits.
|
|
Suppose you want to delete the first word in braces:
|
|
|
|
echo {one} {two} {three} | sed 's/{.*}/{}/' # fails
|
|
echo {one} {two} {three} | sed 's/{[^}]*}/{}/' # succeeds
|
|
|
|
's/{.*}/{}/' is not the solution, since the regex '.' will match
|
|
any character, including the close braces. Replace the '.' with
|
|
'[^}]', which signifies a negated character set '[^...]' containing
|
|
anything other than a right brace. FWIW, we know that 's/{one}/{}/'
|
|
would also solve our question, but we're trying to illustrate the
|
|
use of the negated character set: [^anything-but-this].
|
|
|
|
A negated character set should be used for matching words between
|
|
quote marks, for fields separated by commas, and so on. See also
|
|
section 4.12 ("How do I parse a comma-delimited data file?").
|
|
|
|
(2) The '*' metacharacter represents zero or more instances of the
|
|
previous expression. The '*' metacharacter looks for the leftmost
|
|
possible match first and will match zero characters. Thus,
|
|
|
|
echo foo | sed 's/o*/EEE/'
|
|
|
|
will generate 'EEEfoo', not 'fEEE' as one might expect. This is
|
|
because /o*/ matches the null string at the beginning of the word.
|
|
|
|
After finding the leftmost possible match, the '*' is GREEDY; it
|
|
always tries to match the longest possible string. When two or
|
|
three instances of '.*' occur in the same RE, the leftmost instance
|
|
will grab the most characters. Consider this example, which uses
|
|
grouping '\(...\)' to save patterns:
|
|
|
|
echo bar bat bay bet bit | sed 's/^.*\(b.*\)/\1/'
|
|
|
|
What will be displayed is 'bit', never anything longer, because the
|
|
leftmost '.*' took the longest possible match. Remember this rule:
|
|
"leftmost match, longest possible string, zero also matches."
|
|
|
|
5.5. What is CSDPMI*B.ZIP and why do I need it?
|
|
|
|
If you use MS-DOS outside of Windows and try to use GNU sed v1.18
|
|
or 3.02, you may encounter the following error message:
|
|
|
|
no DPMI - Get csdpmi*b.zip
|
|
|
|
"DPMI" stands for DOS Protected Mode Interface; it's basically a
|
|
means of running DOS in Protected Mode (as opposed to Real Mode),
|
|
which allows programs to share resources in extended memory without
|
|
conflicting with one another. Running HIMEM.SYS and EMM386.EXE is
|
|
not enough. The "CSDPMI*B.ZIP" refers to files written by Charles
|
|
Sandmann to provide DPMI services for 32-bit computers (i.e.,
|
|
386SX, 386DX, 486SX, etc.). Download the binary file (the source
|
|
code is also available):
|
|
|
|
http://www.delorie.com/djgpp/dl/ofc/simtel/v2misc/csdpmi5b.zip # binaries
|
|
http://www.delorie.com/djgpp/dl/ofc/simtel/v2misc/csdpmi5s.zip # source
|
|
ftp://ftp.cdrom.com/pub/simtelnet/gnu/djgpp/v2misc/csdpmi5b.zip # binaries
|
|
ftp://ftp.cdrom.com/pub/simtelnet/gnu/djgpp/v2misc/csdpmi5s.zip # source
|
|
|
|
and extract CWSDPMI.EXE, CWSDPR0.EXE and CWSPARAM.EXE from the ZIP
|
|
file. Put all 3 CWS*.EXE files in the same directory as GSED.EXE
|
|
and you're all set. There are DOC files enclosed, but they're
|
|
nearly incomprehensible for the average computer user. (Another
|
|
case of user-vicious documentation.)
|
|
|
|
If you're running Windows and you normally use a DOS session to run
|
|
GNU sed (i.e., you get to a DOS prompt with a resizable window or
|
|
you press Alt-Enter to switch to full-screen mode), you don't need
|
|
the CWS*.EXE files at all, since Windows uses DPMI already.
|
|
|
|
5.6. Where are the man pages for GNU sed?
|
|
|
|
Prior to GNU sed v3.02, there weren't any. Until recently, man
|
|
pages distributed with gsed were borrowed from old sources or from
|
|
other compilations. None of them were "official." GNU sed v3.02 had
|
|
the first real set of official man pages, and the documentation has
|
|
greatly improved with GNU sed version 4.0, which now includes both
|
|
man pages and textinfo pages.
|
|
|
|
5.7. How do I tell what version of sed I am using?
|
|
|
|
Try entering "sed" all by itself on the command line, followed by
|
|
no arguments or parameters. Also, try "sed --version". In a
|
|
pinch, you can also try this:
|
|
|
|
strings sed | grep -i ver
|
|
|
|
Your version of 'strings' must be a version of the Unix utility of
|
|
this name. It should not be the DOS utility STRINGS.COM by Douglas
|
|
Boling.
|
|
|
|
5.8. Does sed issue an exit code?
|
|
|
|
Most versions of sed do not, but check the documentation that came
|
|
with whichever version you are using. GNU sed issues an exit code
|
|
of 0 if the program terminated normally, 1 if there were errors in
|
|
the script, and 2 if there were errors during script execution.
|
|
|
|
5.9. The 'r' command isn't inserting the file into the text.
|
|
|
|
On most versions of sed (but not all), the 'r' (read) and 'w'
|
|
(write) commands must be followed by exactly one space, then the
|
|
filename, and then terminated by a newline. Any additional
|
|
characters before or after the filename are interpreted as *part*
|
|
of the filename. Thus
|
|
|
|
/RE/r insert.me
|
|
|
|
will would try to locate a file called ' insert.me' (note the
|
|
leading space!). If the file was not found, most versions of sed
|
|
say nothing, not even an error message.
|
|
|
|
When sed scripts are used on the command line, every 'r' and 'w'
|
|
must be the last command in that part of the script. Thus,
|
|
|
|
sed -e '/regex/{r insert.file;d;}' source # will fail
|
|
sed -e '/regex/{r insert.file' -e 'd;}' source # will succeed
|
|
|
|
5.10. Why can't I match or delete a newline using the \n escape sequence?
|
|
Why can't I match 2 or more lines using \n?
|
|
|
|
The \n will never match the newline at the end-of-line because the
|
|
newline is always stripped off before the line is placed into the
|
|
pattern space. To get 2 or more lines into the pattern space, use
|
|
the 'N' command or something similar (such as 'H;...;g;').
|
|
|
|
Sed works like this: sed reads one line at a time, chops off the
|
|
terminating newline, puts what is left into the pattern space where
|
|
the sed script can address or change it, and when the pattern space
|
|
is printed, appends a newline to stdout (or to a file). If the
|
|
pattern space is entirely or partially deleted with 'd' or 'D', the
|
|
newline is *not* added in such cases. Thus, scripts like
|
|
|
|
sed 's/\n//' file # to delete newlines from each line
|
|
sed 's/\n/foo\n/' file # to add a word to the end of each line
|
|
|
|
will _never_ work, because the trailing newline is removed _before_
|
|
the line is put into the pattern space. To perform the above tasks,
|
|
use one of these scripts instead:
|
|
|
|
tr -d '\n' < file # use tr to delete newlines
|
|
sed ':a;N;$!ba;s/\n//g' file # GNU sed to delete newlines
|
|
sed 's/$/ foo/' file # add "foo" to end of each line
|
|
|
|
Since versions of sed other than GNU sed have limits to the size of
|
|
the pattern buffer, the Unix 'tr' utility is to be preferred here.
|
|
If the last line of the file contains a newline, GNU sed will add
|
|
that newline to the output but delete all others, whereas tr will
|
|
delete all newlines.
|
|
|
|
To match a block of two or more lines, there are 3 basic choices:
|
|
(1) use the 'N' command to add the Next line to the pattern space;
|
|
(2) use the 'H' command at least twice to append the current line
|
|
to the Hold space, and then retrieve the lines from the hold space
|
|
with x, g, or G; or (3) use address ranges (see section 3.3, above)
|
|
to match lines between two specified addresses.
|
|
|
|
Choices (1) and (2) will put an \n into the pattern space, where it
|
|
can be addressed as desired ('s/ABC\nXYZ/alphabet/g'). One example
|
|
of using 'N' to delete a block of lines appears in section 4.13
|
|
("How do I delete a block of _specific_ consecutive lines?"). This
|
|
example can be modified by changing the delete command to something
|
|
else, like 'p' (print), 'i' (insert), 'c' (change), 'a' (append),
|
|
or 's' (substitute).
|
|
|
|
Choice (3) will not put an \n into the pattern space, but it _does_
|
|
match a block of consecutive lines, so it may be that you don't
|
|
even need the \n to find what you're looking for. Since several
|
|
versions of sed support this syntax:
|
|
|
|
sed '/start/,+4d' # to delete "start" plus the next 4 lines,
|
|
|
|
in addition to the traditional '/from here/,/to there/{...}' range
|
|
addresses, it may be possible to avoid the use of \n entirely.
|
|
|
|
5.11. My script aborts with an error message, "event not found".
|
|
|
|
This error is generated by the csh or tcsh shells, not by sed. The
|
|
exclamation mark (!) is special to csh/tcsh, and if you use it in
|
|
command-line or shell scripts--even within single quotes--it must
|
|
be preceded by a backslash. Thus, under the csh/tcsh shell:
|
|
|
|
sed '/regex/!d' # will fail
|
|
sed '/regex/\!d' # will succeed
|
|
|
|
The exclamation mark should not be prefixed with a backslash when
|
|
the script is called from a file, as "-f script.file".
|
|
|
|
------------------------------
|
|
|
|
6. OTHER ISSUES
|
|
|
|
6.1. I have a certain problem that stumps me. Where can I get help?
|
|
|
|
Post your question on the "sed-users" mailing list (section 2.3.2),
|
|
where many sed users will be able to see your question. You will have
|
|
to subscribe to have posting privileges.
|
|
|
|
Your other alternative is one of these newsgroups:
|
|
|
|
- alt.comp.editors.batch
|
|
- comp.editors
|
|
- comp.unix.questions
|
|
- comp.unix.shell
|
|
|
|
6.2. How does sed compare with awk, perl, and other utilities?
|
|
|
|
Awk is a much richer language with many features of a programming
|
|
language, including variable names, math functions, arrays, system
|
|
calls, etc. Its command structure is similar to sed:
|
|
|
|
address { command(s) }
|
|
|
|
which means that for each line or range of lines that matches the
|
|
address, execute the command(s). In both sed and awk, an address
|
|
can be a line number or a RE somewhere on the line, or both.
|
|
|
|
In program size, awk is 3-10 times larger than sed. Awk has most of
|
|
the functions of sed, but not all. Notably, sed supports
|
|
backreferences (\1, \2, ...) to previous expressions, and awk does
|
|
not have any comparable syntax. (One exception: GNU awk v3.0
|
|
introduced gensub(), which supports backreferences only on
|
|
substitutions.)
|
|
|
|
Perl is a general-purpose programming language, with many features
|
|
beyond text processing and interprocess communication, taking it
|
|
well past awk or other scripting languages. Perl supports every
|
|
feature sed does and has its own set of extended regular
|
|
expressions, which give it extensive power in pattern matching and
|
|
processing. (Note: the standard perl distribution comes with 's2p',
|
|
a sed-to-perl conversion script. See section 3.6 for more info.)
|
|
Like sed and awk, perl scripts do not need to be compiled into
|
|
binary code. Like sed, perl can also run many useful "one-liners"
|
|
from the command line, though with greater flexibility; see
|
|
question 4.41 ("How do I make substitutions in every file in a
|
|
directory, or in a complete directory tree?").
|
|
|
|
On the other hand, the current version of perl is from 8 to 35
|
|
times larger than sed in its executables alone (perl's library
|
|
modules and allied files not included!). Further, for most simple
|
|
tasks such as substitution, sed executes more quickly than either
|
|
perl or awk. All these utilities serve to process input text,
|
|
transforming it to meet our needs . . . or our arbitrary whims.
|
|
|
|
6.3. When should I use sed?
|
|
|
|
When you need a small, fast program to modify words, lines, or
|
|
blocks of lines in a textfile.
|
|
|
|
6.4. When should I NOT use sed?
|
|
|
|
You should not use sed when you have "dedicated" tools which can do
|
|
the job faster or with an easier syntax. Do not use sed when you
|
|
only want to:
|
|
|
|
- print individual lines, based on patterns within the line itself.
|
|
Instead, use "grep".
|
|
|
|
- print blocks of lines, with 1 or more lines of context above or
|
|
below a specific regular expression. Instead, use the GNU version
|
|
of grep as follows:
|
|
|
|
grep -A{number} -B{number} "regex"
|
|
|
|
- remove individual lines, based on patterns within the line
|
|
itself. Instead, use "grep -v".
|
|
|
|
- print line numbers. Instead, use "nl" or "cat -n".
|
|
|
|
- reformat lines or paragraphs. Instead, use "fold", "fmt" or "par".
|
|
|
|
The tr utility is also more suited than sed to some simple tasks. For
|
|
example, to:
|
|
|
|
- delete individual characters. Instead of "s/[a-d]//g", use
|
|
|
|
tr -d "[a-d]"
|
|
|
|
- squeeze sequential characters. Instead of "s/ee*/e/g", use
|
|
|
|
tr -s "{character-set}"
|
|
|
|
- change individual characters. Instead of "y/abcdef/ABCDEF/", use
|
|
|
|
tr "[a-f]" "[A-F]"
|
|
|
|
Note, however, that tr does not support giving input files on the
|
|
command line, so the syntax is:
|
|
|
|
tr {options-and-patterns} < input-file
|
|
|
|
or, to process multiple files:
|
|
|
|
cat input-file1 input-file2 | tr {options-and-patterns}
|
|
|
|
If you have multiple files, using tr instead of sed is often more of
|
|
an exercise than a useful thing. Although sed can perfectly emulate
|
|
certain functions of cat, grep, nl, rev, sort, tac, tail, tr, uniq,
|
|
and other utilities, producing identical output, the native utilities
|
|
are usually optimized to do the job more quickly than sed.
|
|
|
|
6.5. When should I ignore sed and use awk or Perl instead?
|
|
|
|
If you can write the same script in awk or Perl and do it in less
|
|
time, then use Perl or awk. There's no reason to spend an hour
|
|
writing and debugging a sed script if you can do it in Perl in 10
|
|
minutes (assuming that you know Perl already) and if the processing
|
|
time or memory use is not a factor. Don't hunt pheasants with a .22
|
|
if you have a shotgun at your side . . . unless you simply enjoy
|
|
the challenge!
|
|
|
|
Specifically, use awk or perl if you need to:
|
|
|
|
- count fields or words on a line. (awk)
|
|
- count lines in a block or objects in a file.
|
|
- check lengths of strings or do math operations.
|
|
- handle very long lines or need very large buffers. (or gsed)
|
|
- handle binary data (control characters). (perl: binmode)
|
|
- loop through an array or list.
|
|
- test for file existence, filesize, or fileage.
|
|
- treat each paragraph as a line. (well, not always)
|
|
|
|
6.6. Known limitations among sed versions
|
|
|
|
Limits on distributed versions, although source code for most
|
|
versions of free sed allows for modification and recompilation. As
|
|
used below, "no limit" means there is no "fixed" limit. Limits are
|
|
actually determined by one's hardware, memory, operating system,
|
|
and which C library is used to compile sed.
|
|
|
|
6.6.1. Maximum line length
|
|
|
|
GNU sed: no limit
|
|
ssed: no limit
|
|
sedmod v1.0: 4096 bytes
|
|
HHsed v1.5: 4000 bytes
|
|
sed v1.6: [pending]
|
|
|
|
6.6.2. Maximum size for all buffers (pattern space + hold space)
|
|
|
|
GNU sed: no limit
|
|
ssed: no limit
|
|
sedmod v1.0: 4096 bytes
|
|
HHsed v1.5: 4000 bytes
|
|
sed v1.6: [pending]
|
|
|
|
6.6.3. Maximum number of files that can be read with read command
|
|
|
|
GNU sed v3+: no limit
|
|
ssed: no limit
|
|
GNU sed v2.05: total no. of r and w commands may not exceed 32
|
|
sedmod v1.0: total no. of r and w commands may not exceed 20
|
|
sed v1.6: [pending]
|
|
|
|
6.6.4. Maximum number of files that can be written with 'w' command
|
|
|
|
GNU sed v3+: no limit (but typical Unix is 253)
|
|
ssed: no limit (but typical Unix is 253)
|
|
GNU sed v2.05: total no. of r and w commands may not exceed 32
|
|
sedmod v1.0: 10
|
|
HHsed v1.5: 10
|
|
sed v1.6: [pending]
|
|
|
|
6.6.5. Limits on length of label names
|
|
|
|
GNU sed: no limit
|
|
ssed: no limit
|
|
HHsed v1.5: no limit
|
|
sed v1.6: [pending]
|
|
BSD sed: 8 characters
|
|
|
|
Note that GNU sed and ssed both consider a semicolon to terminate a
|
|
label name.
|
|
|
|
6.6.6. Limits on length of write-file names
|
|
|
|
GNU sed: no limit
|
|
ssed: no limit
|
|
HHsed v1.5: no limit
|
|
sed v1.6: [pending]
|
|
BSD sed: 40 characters
|
|
|
|
6.6.7. Limits on branch/jump commands
|
|
|
|
GNU sed: no limit
|
|
ssed: no limit
|
|
HHsed v1.5: 50
|
|
sed v1.6: [pending]
|
|
|
|
As a practical consequence, this means that HHsed will not read
|
|
more than 50 lines into the pattern space via an N command, even if
|
|
the pattern space is only a few hundred bytes in size. HHsed exits
|
|
with an error message, "infinite branch loop at line {nn}".
|
|
|
|
6.7. Known incompatibilities between sed versions
|
|
|
|
6.7.1. Issuing commands from the command line
|
|
|
|
Most versions of sed permit multiple commands to issued on the
|
|
command line, separated by a semicolon (;). Thus,
|
|
|
|
sed 'G;G' file
|
|
|
|
should triple-space a file. However, for non-GNU sed, some commands
|
|
*require* separate expressions on the command line. These include:
|
|
|
|
- all labels (':a', ':more', etc.)
|
|
- all branching instructions ('b', 't')
|
|
- commands to read and write files ('r' and 'w')
|
|
- any closing brace, '}'
|
|
|
|
If these commands are used, they must be the LAST commands of an
|
|
expression. Subsequent commands must use another expression
|
|
(another -e switch plus arguments). E.g.,
|
|
|
|
sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/' files
|
|
|
|
GNU sed, ssed, sed15 and sed16 all permit these commands to be
|
|
followed by a semicolon, so the previous script can be written:
|
|
|
|
sed ':a;s/^.\{1,77\}$/ &/;ta;s/\( *\)\1/\1/' files
|
|
|
|
Versions differ in implementing the 'a' (append), 'c' (change), and
|
|
'i' (insert) commands:
|
|
|
|
sed "/foo/i New text here" # HHsed/sedmod/gsed-30280
|
|
gsed -e "/foo/i\\" -e "New text here" # GNU sed
|
|
sed1 -e "/foo/i" -e "New text here" # one version of sed
|
|
sed2 "/foo/i\ New text here" # another version
|
|
|
|
6.7.2. Using comments (prefixed by the '#' sign)
|
|
|
|
Most versions of sed permit comments to appear in sed scripts only
|
|
on the first line of the script. Comments on line 2 or thereafter
|
|
are not recognized and will generate an error like "unrecognized
|
|
command" or "command [bad-line-here] has trailing garbage".
|
|
|
|
GNU sed, HHsed, sedmod, and HP-UX sed permit comments to appear on
|
|
any line of the script, except after labels and branching commands
|
|
(b,t), *provided* that a semicolon (;) occurs after the command
|
|
itself. This syntax makes sed similar to awk and perl, which use a
|
|
similar commenting structure in their scripts. Thus,
|
|
|
|
# GNU style sed script
|
|
$!N; # except for last line, get next line
|
|
s/^\([0-9]\{5\}\).*\n\1.*//; # if first 5 digits of each line
|
|
# match, delete BOTH lines.
|
|
t skip
|
|
P; # print 1st line only if no match
|
|
:skip
|
|
D; # delete 1st line of pattern space and loop
|
|
#---end of script---
|
|
|
|
is a valid script for GNU-based versions of sed, but is
|
|
unrecognized for most other versions of sed.
|
|
|
|
Finally, if the first two characters in a disk file script are
|
|
"#n", the output is suppressed, exactly as if -n were entered on
|
|
the command line. This is true for the following versions of sed:
|
|
|
|
- ssed v3.57 and above
|
|
- gsed
|
|
- HHsed v1.5
|
|
- sed v1.6
|
|
|
|
This syntax is not recognized by these versions of sed:
|
|
|
|
- ssed v3.45 to v3.50 (other versions untested)
|
|
- sedmod v1.0
|
|
|
|
6.7.3. Special syntax in REs
|
|
|
|
A. HHsed v1.5 (by Howard Helman)
|
|
|
|
The following expressions can be used for /RE/ addresses or in the
|
|
LHS side of a substitution:
|
|
|
|
+ - 1 or more occurrences of previous RE: same as \{1,\}
|
|
\< - boundary between nonword and word character
|
|
\> - boundary between word and nonword character
|
|
|
|
The following expressions can be used for /RE/ addresses or on
|
|
either side of a substitution:
|
|
|
|
\a - bell (ASCII 07, 0x07)
|
|
\b - backspace (ASCII 08, 0x08)
|
|
\e - escape (ASCII 27, 0x1B)
|
|
\f - formfeed (ASCII 12, 0x0C)
|
|
\n - newline (printed as 2 bytes, 0D 0A or ^M^J, in DOS)
|
|
\r - return (ASCII 13, 0x0D)
|
|
\t - tab (ASCII 09, 0x09)
|
|
\v - vertical tab (ASCII 11, 0x0B)
|
|
\xHH - the ASCII character corresponding to 2 hex digits HH.
|
|
|
|
B. sed v1.6 (by Walter Briscoe)
|
|
|
|
sed v1.6 accepts every expression supported by sed v1.5 (above),
|
|
plus the following elements, which can also used in the RHS of a
|
|
substitution (in addition to those listed above):
|
|
|
|
\\~ - insert replacement pattern defined in last s/// command
|
|
(must be used alone in the RHS)
|
|
\l - change next element to lower case
|
|
\L - change remaining elements to lower case
|
|
\u - change next element to upper case
|
|
\U - change remaining elements to upper case
|
|
\e - end case conversion of next element
|
|
\E - end case conversion of remaining elements
|
|
$0 - insert pattern space BEFORE the substitution
|
|
$1-$9 - match Nth word on the pattern space
|
|
|
|
|
|
C. sedmod v1.0 (by Hern Chen)
|
|
|
|
The following expressions can be used for /RE/ addresses in the LHS
|
|
of a substitution:
|
|
|
|
+ - 1 or more occurrences of previous RE: same as \{1,\}
|
|
\a - any alphanumeric: same as [a-zA-Z0-9]
|
|
\A - 1 or more alphas: same as \a+
|
|
\d - any digit: same as [0-9]
|
|
\D - 1 or more digits: same as \d+
|
|
\h - any hex digit: same as [0-9a-fA-F]
|
|
\H - 1 or more hexdigits: same as \h+
|
|
\l - any letter: same as [A-Za-z]
|
|
\L - 1 or more letters: same as \l+
|
|
\n - newline (read as 2 bytes, 0D 0A or ^M^J, in DOS)
|
|
\s - any whitespace character: space, tab, or vertical tab
|
|
\S - 1 or more whitespace chars: same as \s+
|
|
\t - tab (ASCII 09, 0x09)
|
|
\< - boundary between nonword and word character
|
|
\> - boundary between word and nonword character
|
|
|
|
The following expressions can be used in the RHS of a substitution.
|
|
"Elements" refer to \1 .. \9, &, $0, or $1 .. $9:
|
|
|
|
& - insert regexp defined on LHS
|
|
\e - end case conversion of next element
|
|
\E - end case conversion of remaining elements
|
|
\l - change next element to lower case
|
|
\L - change remaining elements to lower case
|
|
\n - newline (printed as 2 bytes, 0D 0A or ^M^J, in DOS)
|
|
\t - tab (ASCII 09, 0x09)
|
|
\u - change next element to upper case
|
|
\U - change remaining elements to upper case
|
|
$0 - insert the original pattern space
|
|
$1-$9 - match Nth word on the pattern space
|
|
|
|
D. UnixDos sed
|
|
|
|
The following expressions can be used in text, LHS, and RHS:
|
|
|
|
\n - newline (printed as 2 bytes, 0D 0A or ^M^J, in DOS)
|
|
|
|
E. GNU sed v1.03 (by Frank Whaley)
|
|
|
|
When used with the -x (extended) switch on the command line, or
|
|
when '#x' occurs as the first line of a script, Whaley's gsed103
|
|
supports the following expressions in both the LHS and RHS of a
|
|
substitution:
|
|
|
|
\| matches the expression on either side
|
|
? 0 or 1 occurrences of previous RE: same as \{0,1\}
|
|
+ 1 or more occurrence of previous RE: same as \{1,\}
|
|
\a "alert" beep (BEL, Ctrl-G, 0x07)
|
|
\b backspace (BS, Ctrl-H, 0x08)
|
|
\f formfeed (FF, Ctrl-L, 0x0C)
|
|
\n newline (LF, Ctrl-J, 0x0A)
|
|
\r carriage-return (CR, Ctrl-M, 0x0D)
|
|
\t horizontal tab (HT, Ctrl-I, 0x09)
|
|
\v vertical tab (VT, Ctrl-K, 0x0B)
|
|
\bBBB binary char, where BBB are 1-8 binary digits, [0-1]
|
|
\dDDD decimal char, where DDD are 1-3 decimal digits, [0-9]
|
|
\oOOO octal char, where OOO are 1-3 octal digits, [0-7]
|
|
\xHH hex char, where HH are 1-2 hex digits, [0-9A-F]
|
|
|
|
In normal mode, with or without the -x switch, the following escape
|
|
sequences are also supported in regex addressing or in the LHS of a
|
|
substitution:
|
|
|
|
\` matches beginning of pattern space: same as /^/
|
|
\' matches end of pattern space: same as /$/
|
|
\B boundary between 2 word or 2 nonword characters
|
|
\w any nonword character [*BUG!* should be a word char]
|
|
\W any nonword character: same as /[^A-Za-z0-9]/
|
|
\< boundary between nonword and word char
|
|
\> boundary between word and nonword char
|
|
|
|
F. GNU sed v2.05 and higher versions
|
|
|
|
The following expressions can be used for /RE/ addresses or in the
|
|
LHS side of a substitution:
|
|
|
|
\` - matches the beginning of the pattern space (same as "^")
|
|
\' - matches the end of the pattern space (same as "$")
|
|
\? - 0 or 1 occurrence of previous character: same as \{0,1\}
|
|
\+ - 1 or more occurrences of previous character: same as \{1,\}
|
|
\| - matches the string on either side, e.g., foo\|bar
|
|
\b - boundary between word and nonword chars (reversible)
|
|
\B - boundary between 2 word or between 2 nonword chars
|
|
\n - embedded newline (usable after N, G, or similar commands)
|
|
\w - any word character: [A-Za-z0-9_]
|
|
\W - any nonword char: [^A-Za-z0-9_]
|
|
\< - boundary between nonword and word character
|
|
\> - boundary between word and nonword character
|
|
|
|
On \b, \B, \<, and \>, see section 6.7.4 ("Word boundaries"),
|
|
below.
|
|
|
|
Undocumented -r switch:
|
|
|
|
Beginning with version 3.02, GNU sed has an undocumented -r switch
|
|
(undocumented till version 4.0), activating Extended Regular
|
|
Expressions in the following manner:
|
|
|
|
? - 0 or 1 occurrence of previous character
|
|
+ - 1 or more occurrences of previous character
|
|
| - matches the string on either side, e.g., foo|bar
|
|
(...) - enable grouping without backslash
|
|
{...} - enable interval expression without backslash
|
|
|
|
When the -r switch (mnemonic: "regular expression") is used, prefix
|
|
these symbols with a backslash to disable the special meaning.
|
|
|
|
Escape sequences:
|
|
|
|
Beginning with version 3.02.80, the following escape sequences can
|
|
now be used on both sides of a "s///" substitution:
|
|
|
|
\a "alert" beep (BEL, Ctrl-G, 0x07)
|
|
\f formfeed (FF, Ctrl-L, 0x0C)
|
|
\n newline (LF, Ctrl-J, 0x0A)
|
|
\r carriage-return (CR, Ctrl-M, 0x0D)
|
|
\t horizontal tab (HT, Ctrl-I, 0x09)
|
|
\v vertical tab (VT, Ctrl-K, 0x0B)
|
|
\oNNN a character with the octal value NNN
|
|
\dNNN a character with the decimal value NNN
|
|
\xHH a character with the hexadecimal value HH
|
|
|
|
Note that GNU sed also supports "character classes", a POSIX
|
|
extension to regexes, described in section 3.7, above.
|
|
|
|
G. sed 4.0 and higher versions
|
|
|
|
The following expressions can be used in the RHS of a substitution.
|
|
|
|
\e - end case conversion
|
|
\l - change next character to lower case
|
|
\L - change remaining text to lower case
|
|
\n - newline (printed as 2 bytes, 0D 0A or ^M^J, in DOS)
|
|
\t - tab (ASCII 09, 0x09)
|
|
\u - change next character to upper case
|
|
\U - change remaining text to upper case
|
|
|
|
In addition, GNU sed 4.0 can modify the way ^ and $ are interpreted,
|
|
so that ^ can also match an empty string after a newline character,
|
|
and $ can also match an empty string before a newline character (to
|
|
do this, add an "M" after the regular expression terminator, like
|
|
/^>/M -- see section 3.1.1). Even if you use this feature, \` and \'
|
|
still match the beginning and the end of the pattern space,
|
|
respectively.
|
|
|
|
H. ssed
|
|
|
|
Everything that was said for GNU sed applies to ssed as well. In
|
|
addition, in Perl-mode (-R switch), these become active or inactive:
|
|
|
|
. - no longer matches new-line characters
|
|
\A - matches beginning of pattern space
|
|
\Z - matches end of pattern space or last newline in the PS
|
|
\z - matches end of pattern space
|
|
\d - matches any digit: same as [0-9]
|
|
\D - matches any non-digit: same as [^0-9]
|
|
\` - no longer matches beginning of pattern space
|
|
\' - no longer matches end of pattern space
|
|
\< - no longer matches boundary between nonword & word char
|
|
\> - no longer matches boundary between word & nonword char
|
|
\oNNN - no longer matches char with octal value NNN
|
|
\dNNN - no longer matches char with decimal value NNN
|
|
\NNN - matches char with octal value NNN
|
|
|
|
Perl mode supports lookahead (?=match) and lookbehind (?<=match)
|
|
pattern matching. The matched text is NOT captured in "&" for s///
|
|
replacements!
|
|
|
|
foo(?=bar) - match "foo" only if "bar" follows it
|
|
foo(?!bar) - match "foo" only if "bar" does NOT follow it
|
|
(?<=foo)bar - match "bar" only if "foo" precedes it
|
|
(?<!foo)bar - match "bar" only if "foo" does NOT precede it
|
|
|
|
(?<!in|on|at)foo
|
|
- match "foo" only if NOT preceded by "in", "on" or "at"
|
|
(?<=\d{3})(?<!999)foo
|
|
- match "foo" only if preceded by 3 digits other than "999"
|
|
|
|
In Perl mode, there are two new switches in /addressing/ or s///
|
|
commands. Switches may be lowercase in s/// commands, but must be
|
|
uppercase in /addressing/:
|
|
|
|
/S - lets "." match a newline also
|
|
/X - extra whitespace is ignored. See below, for sample usage.
|
|
|
|
Here are some examples of Perl-style regular expressions. Use the -R
|
|
switch.
|
|
|
|
(?i)abc - case-insensitive match of abc, ABC, aBc, ABc, etc.
|
|
ab(?i)c - same as above; the (?i) applies throughout the pattern
|
|
(ab(?i)c) - matches abc or abC; the outer parens make the difference!
|
|
(?m) - multi-line pattern space: same as "s/FIND/REPL/M"
|
|
(?s) - set "." to match newline also: same as "s/FIND/REPL/S"
|
|
(?x) - ignore whitespace and #comments; see section (9) below.
|
|
|
|
(?:abc)foo - match "abcfoo", but do not capture 'abc' in \1
|
|
(?:ab|cd)ef - match "abef" or "cdef"; only 'cd' is captured in \1
|
|
(?#remark)xy - match "xy"; remarks after "#" are ignored.
|
|
|
|
And here are some sample uses of /X switch to add comments to complex
|
|
expressions. To embed literal spaces, precede with \ or put inside
|
|
[brackets].
|
|
|
|
# ssed script to change "(123) 456-7890" into "[ac123] 456-7890"
|
|
#
|
|
s/ # BACKSLASH IS NEEDED AT END OF EACH LINE! \
|
|
\( # literal left paren, ( \
|
|
(\d{3}) # 3 digits \
|
|
\) # literal right paren, ) \
|
|
[ \t]* # zero or more spaces or tabs \
|
|
(\d{3}-\d{4}) # 3 digits, hyphen, 4 digits \
|
|
/[ac\1] \2/gx; # replace g(lobally), with e(x)tended spacing
|
|
|
|
6.7.4. Word boundaries
|
|
|
|
GNU sed, ssed, sed16, sed15 and sedmod use certain symbols to define
|
|
the boundary between a "word character" and a nonword character. A
|
|
word character fits the regex "[A-Za-z0-9_]". Note: a word character
|
|
includes the underscore "_" but not the hyphen, probably because the
|
|
underscore is permissible as a label in sed and in other scripting
|
|
languages. (In gsed103, a word character did NOT include the
|
|
underscore; it included alphanumerics only.)
|
|
|
|
These symbols include '\<' and '\>' (gsed, ssed, sed15, sed16,
|
|
sedmod) and '\b' and '\B' (gsed only). Note that the boundary
|
|
symbols do not represent a character, but a position on the line.
|
|
Word boundaries are used with literal characters or character sets
|
|
to let you match (and delete or alter) whole words without
|
|
affecting the spaces or punctuation marks outside of those words.
|
|
They can only be used in a "/pattern/" address or in the LHS of a
|
|
's/LHS/RHS/' command. The following table shows how these symbols
|
|
may be used in HHsed and GNU sed. Sedmod matches the syntax of
|
|
HHsed.
|
|
|
|
Match position Possible word boundaries HHsed GNU sed
|
|
---------------------------------------------------------------
|
|
start of word [nonword char]^[word char] \< \< or \b
|
|
end of word [word char]^[nonword char] \> \> or \b
|
|
middle of word [word char]^[word char] none \B
|
|
outside of word [nonword char]^[nonword char] none \B
|
|
---------------------------------------------------------------
|
|
|
|
In ssed, the symbols '\<' and '\>' lose their special meaning when
|
|
the -R switch is used to invoke Perl-style expressions. However,
|
|
the identical meaning of '\<' and '\>' can be obtained through
|
|
these nonmatching, zero-width assertions:
|
|
|
|
(?<!\w)(?=\w) and (?<=\w)(?!\w)
|
|
|
|
6.7.5. Commands which operate differently
|
|
|
|
A. GNU sed version 3.02 and 3.02.80
|
|
|
|
The N command no longer discards the contents of the pattern space
|
|
upon reaching the end of file. This is not a bug, it's a feature.
|
|
However, it breaks certain scripts which relied on the older
|
|
behavior of N.
|
|
|
|
'N' adds the Next line to the pattern space, enabling multiple
|
|
lines to be stored and acted upon. Upon reaching the last line of
|
|
the file, if the N command was issued again, the contents of the
|
|
pattern space would be silently deleted and the script would abort
|
|
(this has been the traditional behavior). For this reason, sed
|
|
users generally wrote:
|
|
|
|
$!N; # to add the Next line to every line but the last one.
|
|
|
|
However, certain sed scripts relied on this behavior, such as the
|
|
script to delete trailing blank lines at the end of a file (see
|
|
script #12 in section 3.2, "Common one-line sed scripts", above).
|
|
Also, classic textbooks such as Dale Dougherty and Arnold Robbins'
|
|
_sed & awk_ documented the older behavior.
|
|
|
|
The GNU sed maintainer felt that despite the portability problems
|
|
this would cause, changing the N command to print (rather than
|
|
delete) the pattern space was more consistent with one's intuitions
|
|
about how a command to "append the Next line" _ought_ to behave.
|
|
Another fact favoring the change was that "{N;command;}" will
|
|
delete the last line if the file has an odd number of lines, but
|
|
print the last line if the file has an even number of lines.
|
|
|
|
To convert scripts which used the former behavior of N (deleting
|
|
the pattern space upon reaching the EOF) to scripts compatible with
|
|
all versions of sed, change a lone "N;" to "$d;N;".
|
|
|
|
------------------------------
|
|
|
|
7. KNOWN BUGS AMONG SED VERSIONS
|
|
|
|
Most versions of GNU sed and ssed contain a "buglist" in the
|
|
archive source code of known errors or reported behaviors that may
|
|
be misconstrued as bugs. This portion of the sed FAQ does _not_
|
|
attempt to fully reproduce those buglists files. However, we do
|
|
seek to do some substantial reporting, particularly where certain
|
|
programs have no "buglist" of their own or are not being actively
|
|
maintained.
|
|
|
|
As a rule of thumb, if the bug "bites" someone on the sed-users
|
|
mailing list, I tend to report it.
|
|
|
|
7.1. ssed v3.59 (by Paolo Bonzini)
|
|
|
|
(1) N does not discard the contents of the pattern space upon
|
|
reaching the end of file; not a bug. See section 6.7.5.A, above.
|
|
|
|
(2) If \x26 is entered into the RHS of a substitution, it is
|
|
interpreted as an ampersand metacharacter, and the entire pattern
|
|
matched in the "find" portion is inserted at that point. A literal
|
|
ampersand should be inserted instead.
|
|
|
|
(3) Under Windows 2000, the -i switch doesn't create backup files
|
|
properly. When passed one or more files to process, the source
|
|
file(s) are unchanged, and the output changed files are given
|
|
filenames like sedDOSxyz with no way to correspond them with the
|
|
names of the source files.
|
|
|
|
7.2. GNU sed v4.0 - v4.0.5
|
|
|
|
(1) N does not discard the contents of the pattern space upon
|
|
reaching the end of file; not a bug. See section 6.7.5.A, above.
|
|
|
|
(2) If \x26 is entered into the RHS of a substitution, it is
|
|
interpreted as an ampersand metacharacter, and the entire pattern
|
|
matched in the "find" portion is inserted at that point. A literal
|
|
ampersand should be inserted instead.
|
|
|
|
7.3. GNU sed v3.02.80
|
|
|
|
(1) N does not discard the contents of the pattern space upon
|
|
reaching the end of file; not a bug. See section 6.7.5.A, above.
|
|
|
|
(2) Same as #2 for GNU sed v4.0, above.
|
|
|
|
7.4. GNU sed v3.02
|
|
|
|
(1) Affects only v3.02 binaries compiled with DJGPP for MS-DOS and
|
|
MS-Windows: 'l' (list) command does not display a lone carriage
|
|
return (0x0D, ^M) embedded in a line.
|
|
|
|
(2) The expression "\<" causes problems when attempting the
|
|
following types of substitutions, which should print "+aaa +bbb":
|
|
|
|
echo aaa bbb | sed 's/\</+/g' # prints "+a+a+a +b+b+b"
|
|
echo aaa bbb | sed 's/\<./+&/g' # prints "+a+a+a +b+b+b"
|
|
|
|
(3) The N command no longer discards the contents of the pattern
|
|
space upon reaching the end of file. This is not a bug, it's a
|
|
feature. See section 6.7.5, "Commands which operate differently".
|
|
|
|
7.5. GNU sed v2.05
|
|
|
|
(1) If a number follows the substitute command (e.g., s/f/F/10) and
|
|
the number exceeds the possible matches on the pattern space, the
|
|
command 't label' _always_ jumps to the specified label. 't' should
|
|
jump only if the substitution was successful (or returned "true").
|
|
|
|
(2) 'l' (list) command does not convert the following characters to
|
|
hex values, but passes them through unchanged: 0xF7, 0xFB, 0xFC,
|
|
0xFD, 0xFE.
|
|
|
|
(3) A range address like "/foo/,14" is supposed to match every line
|
|
from the first occurrence of "foo" until line 14, inclusive, and
|
|
then match only those lines containing "foo" thereafter. In gsed
|
|
v2.05, if "foo" occurs later in the file, every line from there to
|
|
the end of file will be matched (since gsed is looking for line 14
|
|
to occur again!).
|
|
|
|
(4) The regexes /\`/ and /\'/ are not interpreted as a backquote
|
|
and apostrophe, as might be expected. Instead, they are used to
|
|
represent the beginning-of-line and end-of-line (respectively), to
|
|
conform with similar regexes in the GNU versions of Emacs and awk.
|
|
As a consequence, there is no clear way to indicate an apostrophe,
|
|
since a bare apostrophe (') has special meaning to the Unix shell
|
|
and the quoted apostrophe (\') is interpreted as the EOL. A
|
|
double-quote apostrophe (\\') was interpreted as a backslash to sed
|
|
and a quote mark to the shell--again, not providing the expected
|
|
results. This syntax changed in the next version of gsed.
|
|
|
|
(5) Multiple occurrences of the 'w' command fail, as shown here,
|
|
given that both "aaa" and "bbb" occur within the file:
|
|
|
|
gsed -e "/aaa/w FILE" -e "/bbb/w FILE" input.txt
|
|
|
|
(6) The expression "\<" causes problems when attempting the
|
|
following type of substitution, which should print "+aaa +bbb":
|
|
|
|
echo aaa bbb | sed 's/\</+/g' # sed hangs up with no output
|
|
|
|
The syntax 's/\<./+&/g' issues the proper output.
|
|
|
|
7.6. GNU sed v1.18
|
|
|
|
(1) Same as #1 for GNU sed v2.05, above.
|
|
|
|
(2) The following command will lock the computer under Win95. Echos
|
|
is an echo command that does not issue a trailing newline:
|
|
|
|
echos any_word | gsed "s/[ ]*$//"
|
|
|
|
(3) Same as #3 for GNU sed v2.05, above.
|
|
|
|
7.7. GNU sed v1.03 (by Frank Whaley)
|
|
|
|
(1) The \w and \W escape sequences both match only nonword
|
|
characters. \w is misdefined and should match word characters.
|
|
|
|
(2) The underscore is defined as a nonword character; it should be
|
|
defined as a word character.
|
|
|
|
(3) same as #3 for GNU sed v2.05, above.
|
|
|
|
7.8. sed v1.6 (by Walter Briscoe) - still in beta version
|
|
|
|
(1) Duplicated subexpressions (still) do not match an empty set as
|
|
they should. This problem was inherited from HHsed15.
|
|
|
|
echo 123 | sed "s/\([a-z][a-z]\)*/=\1/" # does not return '='
|
|
|
|
(2) If grouping is followed by a + operator, nothing is matched.
|
|
This problem was inherited from HHsed; it fixed a bug with the *
|
|
operator, but the problem with the + operator persists.
|
|
|
|
echo aaa | sed "/\(a\)+/d" # nothing is deleted.
|
|
|
|
(3) With the interval expressions \{1,\} and +, there is a bug
|
|
related to the & replacement character. This affected the BETA
|
|
release, and it's not known if it affects the final release.
|
|
|
|
echo ab | sed "s/a[^a]*/&c/" # returns 'abc'. Okay.
|
|
echo ab | sed "s/a[^a]+/&c/" # returns 'ab'. Bug!
|
|
echo ab | sed "s/a[^a]\{1,\}/&c/" # returns 'ab'. Bug!
|
|
|
|
7.9. HHsed v1.5 (by Howard Helman)
|
|
|
|
(1) If a number follows the substitute command (e.g., s/foo/bar/2),
|
|
in a sed script entered from the command line, two semicolons must
|
|
follow the number, or they must be separated by an -e switch.
|
|
Normally, only 1 semicolon is needed to separate commands.
|
|
|
|
echo bit bet | HHsed "s/b/n/2;;s/b/B/" # solution 1
|
|
echo bit bet | HHsed -e "s/b/n/2" -e "s/b/B" # solution 2
|
|
|
|
(2) If the substitute command is followed by a number and a "p"
|
|
flag, when the -n switch is used, the "p" flag must occur first.
|
|
|
|
echo aaa | HHsed -n "s/./B/3p" # bug! nothing prints
|
|
echo aaa | HHsed -n "s/./B/p3" # prints "aaB" as expected
|
|
|
|
(3) The following commands will cause HHsed to lock the computer
|
|
under MS-DOS or Win95. Note that they occur because of malformed
|
|
regular expressions which will match no characters.
|
|
|
|
sed -n "p;s/\<//g;" file
|
|
sed -n "p;s/[char-set]*//g;" file
|
|
|
|
(4) The range command '/RE1/,/RE2/' in HHsed will match one line if
|
|
both regexes occur on the same line (see section 3.4(3), above).
|
|
Though this could be construed as a feature, it should probably be
|
|
considered a bug since its operation differs from every other
|
|
version of sed. For example, '/----/,/----/{s/^/>>/;}' should put
|
|
two angle brackets ">>" before every line which is sandwiched
|
|
between a row of 4 or more hyphens. With HHsed, this command will
|
|
only prefix the hyphens themselves with the angle brackets.
|
|
|
|
(5) If the hold space is empty, the H command copies the pattern
|
|
space to the hold space but fails to prepend a leading newline. The
|
|
H command is supposed to add a newline, followed by the contents of
|
|
the pattern space, to the hold space at all times. A workaround is
|
|
"{G;s/^\(.*\)\(\n\)$/\2\1/;H;s/\n$//;}", but it requires knowing
|
|
that the hold space is empty and using the command only once.
|
|
Another alternative is to use the G or the h command alone at key
|
|
points in the script.
|
|
|
|
(6) If grouping is followed by an '*' or '+' operator, HHsed does
|
|
not match the pattern, but issues no warning. See below:
|
|
|
|
echo aaa | HHsed "/\(a\)*/d" # nothing is deleted
|
|
echo aaa | HHsed "/\(a\)+/d" # nothing is deleted
|
|
echo aaa | HHsed "s/\(a\)*/\1B/" # nothing is changed
|
|
echo aaa | HHsed "s/\(a\)+/\1B/" # nothing is changed
|
|
|
|
(7) If grouping is followed by an interval expression, HHsed halts
|
|
with the error message "garbled command", in all of the following
|
|
examples:
|
|
|
|
echo aaa | HHsed "/\(a\)\{3\}/d"
|
|
echo aaa | HHsed "/\(a\)\{1,5\}/d"
|
|
echo aaa | HHsed "s/\(a\)\{3\}/\1B/"
|
|
|
|
(8) In interval expressions, 0 is not supported. E.g., \{0,3\)
|
|
|
|
7.10. sedmod v1.0 (by Hern Chen)
|
|
|
|
Technically, the following are limits (or features?) of sedmod, not
|
|
bugs, since the docs for sedmod do not claim to support these
|
|
missing features.
|
|
|
|
(1) sedmod does not support standard interval expressions \{...\}
|
|
present in nearly all versions of sed.
|
|
|
|
(2) If grouping is followed by an '*' or '+' operator, sedmod gives
|
|
a "garbled command" message. However, if the grouped expressions
|
|
are strings literals with no metacharacters, a partial workaround
|
|
can be done like so:
|
|
|
|
\(string\)\1* # matches 1 or more instances of 'string'
|
|
\(string\)\1+ # matches 2 or more instances of 'string'
|
|
|
|
(3) sedmod does not support a numeric argument after the s///
|
|
command, as in 's/a/b/3', present in nearly all versions of sed.
|
|
|
|
The following are bugs in sedmod v1.0:
|
|
|
|
(4) When the -i (ignore case) switch is used, the '/regex/d'
|
|
command is not properly obeyed. Sedmod may miss one or more lines
|
|
matching the expression, regardless of where they occur in the
|
|
script. Workaround: use "/regex/{d;}" instead.
|
|
|
|
7.11. HP-UX sed
|
|
|
|
(1) Versions of HP-UX sed up to and including version 10.20 are
|
|
buggy. According to the README file, which comes with the GNU cc
|
|
at <ftp://ftp.ntua.gr/pub/gnu/sed/sed-2.05.bin.README>:
|
|
|
|
"When building gcc on a hppa*-*-hpux10 platform, the `fixincludes'
|
|
step (which involves running a sed script) fails because of a bug
|
|
in the vendor's implementation of sed. Currently the only known
|
|
workaround is to install GNU sed before building gcc. The file
|
|
sed-2.05.bin.hpux10 is a precompiled binary for that platform."
|
|
|
|
7.12. SunOS sed v4.1
|
|
|
|
(1) Bug occurs in RE pattern matching when a non-null '[char-set]*'
|
|
is followed by a null '\NUM' pattern recall, illustrated here and
|
|
reported by Greg Ubben:
|
|
|
|
s/\(a\)\(b*\)cd\1[0-9]*\2foo/bar/ # between '[0-9]*' and '\2'
|
|
s/\(a\{0,1\}\).\{0,1\}\1/bar/ # between '.\{0,1\}' and '\1'
|
|
|
|
Workaround: add a do-nothing 'X*' expression which will not match
|
|
any characters on the line between the two components. E.g.,
|
|
|
|
s/\(a\)\(b*\)cd\1[0-9]*X*\2foo/bar/
|
|
s/\(a\{0,1\}\).\{0,1\}X*\1/bar/
|
|
|
|
7.13. SunOS sed v5.6
|
|
|
|
(1) If grouping is followed by an asterisk, SunOS sed does not match
|
|
the null string, which it should do. The following command:
|
|
|
|
echo foo | sed 's/f\(NO-MATCH\)*/g\1/'
|
|
|
|
should transform "foo" to "goo" under normal versions of sed.
|
|
|
|
7.14. Ultrix sed v4.3
|
|
|
|
(1) If grouping is followed by an asterisk, Ultrix sed replies with
|
|
"command garbled", as shown in the following example:
|
|
|
|
echo foo | sed 's/f\(NO-MATCH\)*/g\1/'
|
|
|
|
(2) If grouping is followed by a numeric operator such as \{0,9\},
|
|
Ultrix sed does not find the match.
|
|
|
|
7.15. Digital Unix sed
|
|
|
|
(1) The following comes from the man pages for sed distributed with
|
|
new, 1998 versions of Digital Unix (reformatted to fit our
|
|
margins):
|
|
|
|
[Digital] The h subcommand for sed does not work properly. When
|
|
you use the h subcommand to place text into the hold area, only
|
|
the last line of the specified text is saved. You can use the H
|
|
subcommand to append text to the hold area. The H subcommand and
|
|
all others dealing with the hold area work correctly.
|
|
|
|
(2) "$d" command issues an error message, "cannot parse". Reported
|
|
by Carlos Duarte on 8 June 1998.
|
|
|
|
[end-of-file]
|