Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!news.albasani.net!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Stephane CHAZELAS Newsgroups: comp.unix.shell,comp.unix.programmer,comp.programming.contests Subject: Re: The First Pure Shell Contest (PUSH): relativepath Date: Sun, 21 Aug 2011 16:19:43 +0000 (UTC) Organization: A noiseless patient Spider Lines: 37 Message-ID: References: <9b7kg7F3njU1@mid.individual.net> <87fwkuzw9r.fsf@sapphire.mobileactivedefense.com> Injection-Date: Sun, 21 Aug 2011 16:19:43 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="qzG0Li1iwhS8BRIL3GjZtw"; logging-data="25746"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/CuXSHd9b1U18hOiV/AH4yPTG5+Jak3ubDOdR2KLg8Iw==" User-Agent: slrn/pre1.0.0-18 (Linux) Cancel-Lock: sha1:z+CFiI1kOm5ZJ6xTNOALZ4TlnMA= Mail-Copies-To: nobody Xref: x330-a1.tempe.blueboxinc.net comp.unix.shell:1778 comp.unix.programmer:1175 comp.programming.contests:23 2011-08-21, 15:14(+01), Rainer Weikusat: > Stephane CHAZELAS writes: >> 2011-08-19, 17:23(+00), Jens Schweikhardt: >> [...] >>> Write a POSIX shell function named 'relativepath' which takes as >>> arguments two absolute canonicalized pathnames, and stores the relative >>> path from the first to the second in the variable "result" or "." when >>> the arguments are the same. Example: relativepath /foo/bar /foo/baz sets >>> result to "../baz". >> [...] >> >> In the not-answering-the-question category, what about: >> >> printf '%s\n' "$1//$2/"|sed -e:1 -e'$!{N;b1' -e} -e' >> s|/////*|///|;s|\(.*/\)\(.*/\)\1|\2|;:2 >> s|^[^/]*/\(\(.*/\)*/\)|\1../|;t2 >> s|^/||;s|/$||;s/^$/./' > > It's a nice demonstration that some people really excel in the art of > creating complicated solutions to simple problems. It might look complicated as sed is not very verbose, but it's quite simple. The core is in one substitution and one loop with only one substitution per iteration. sed is the only POSIX tool I know that has a built-in way to find the longest leading common string in two strings (well, with expr(1)(*) and ex/vi) which makes it probably the best tool for the task which is what "pure shell programming" should be IMO. (*) $ expr 'foobarbaz foobarfoo' : '\(.*\).* \1' foobar -- Stephane