home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.unix.shell:3101 comp.unix.questions:9332
- Newsgroups: comp.unix.shell,comp.unix.questions
- Path: sparky!uunet!munnari.oz.au!metro!physiol.su.OZ.AU!john
- From: john@physiol.su.OZ.AU (John Mackin)
- Subject: Re: What's wrong with this sed command?
- Message-ID: <1992Jul23.090023.17661@physiol.su.OZ.AU>
- Summary: A lot
- Organization: Department of Physiology, University of Sydney, Australia
- References: <MONTNARO.92Jul21160321@ausable.crd.ge.com> <glaze.2520@glaze>
- Date: Thu, 23 Jul 1992 09:00:23 GMT
- Lines: 82
-
- Below, > is someone called `Glaze' who seemed to go to some trouble to
- conceal their identity (either that, or their software is more broken
- than I can easily believe), and >> is Glaze quoting the original poster,
- whose identity Glaze chose to suppress -- and unfortunately my news
- machine doesn't have the original article.
-
- >> I'm trying to use sed to trim off all leading "./" patterns from source
- >> filenames in make rules. On an IBM RS6000 the following works as I expected:
- >>
- >> echo 'enquire.o: ./././enquire.c' | sed 's?: \(\./\)\{1,\}?: ?'
- >> yielding
- >> enquire.o: enquire.c
- >>
- >> On our other systems (Sun-4, HP, SGI, and Motorola 68040) it prints
- >> different results. The HP doesn't trim any "./" patterns, while the Sun,
- >> Moto, and SGI all trim one pattern.
- >>
- >> Have I incorrectly specified the sed command or are one (or more) of the
- >> vendors' sed implementations incorrect? If so, which one(s)? I'm inclined to
- >> believe the IBM is correct and the others are bugged.
- >
- > I'm inclined to believe the IBM is incorrect and most of the others are
- > correct. Your sed should be trying to match ONE pattern of the form
- > ": ./"[blah] and it does(on most machines) and replaces it. What you
- > want is for it to match multiple "./"s after the ": ", so try
- > echo 'enquire.o: ./././enquire.c' | sed 's?: [\./]*?: ?'
-
- Glaze's inclination is into error. The real question the original
- poster has to ask himself (yes, I know it's a sexist usage, but I
- couldn't bring myself to write "themself") here is: do I want this
- sed script to be -portable-?? If you do, then you cannot do this in this
- way with sed (as I explain below). If you only care about what it
- does on one particular machine, and you just want to know what
- behaviour is `correct', then you have to define your standard of
- correctness.
-
- Now, some people might call me reactionary, but to me, the standard
- of correctness for Unix commands is the Seventh Edition manuals.
- These were published by HRW, and were once widely available; I don't
- know if they are still in print. I've looked in my copy, and neither
- the sed manual entry nor the sed paper in Volume 2 says one word about
- any \{m,n\} stuff. Therefore, if I were writing a sed script that I
- wanted to be portable, I would not use such stuff. For my money,
- the only one of the original poster's machines that is doing the
- right thing is the HP: it is all the others that have sed bugs here.
- (My Ultrix 4.2 DECstation (unsurprisingly -- DEC don't break the commands,
- in general) does the same thing, stripping nothing.)
-
- As for Glaze's proposed solution, I am afraid it is bogus. Yes, it
- will `work', in that it will strip as many ./'s as are there,
- but it will also strip, for example, "...///" -- it will strip
- _any combination of dot and slash (and backslash, see below)
- characters in the target position_, which is hardly what the
- original poster wanted.
-
- The other error in Glaze's proposal involves the backslash inside
- the square brackets. In a character class, there are no metacharacters,
- and writing a backslash introduces a backslash into the class.
- So the `correct' way to write Glaze's command would be:
-
- sed 's?: [./]*?: ?'
-
- What the original poster wants cannot be done in one step with the ed
- subset of regular expressions (as used by sed). If sed accepted full regular
- expressions, a la egrep, then the command would be:
-
- sed 's?: (\./)*?: ?' WRONG WRONG WRONG
-
- but since sed doesn't do full RE's, that won't work. You need
- another approach. Since you can't do it in one step, do it
- in several:
-
- sed -e ': loop' -e 's?: ./?: ?' -e 't loop'
-
- Easy, and I will bet it will work in the great majority of vendor-busted
- sed's out there.
-
- Moral: know your tools.
-
- --
- John Mackin <john@physiol.su.oz.au>
- `Even the white bits are black.'
-