help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] Transform strings with special characters so that the st


From: Stephane Chazelas
Subject: Re: [Help-bash] Transform strings with special characters so that the strings don't need to be quoted?
Date: Mon, 30 Mar 2015 14:02:10 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

2015-03-30 07:55:45 -0400, Greg Wooledge:
> On Sun, Mar 29, 2015 at 10:41:53AM +0100, Stephane Chazelas wrote:
> > ksh93 doesn't need a -v because it doesn't fork+pipe in
> > var=$(printf %s "$var") (and that output will never end in a
> > newline character).

Sorry, I obviously meant:

> > ksh93 doesn't need a -v because it doesn't fork+pipe in
> > var=$(printf %q "$var") (and that output will never end in a
                 ^^
> > newline character).

It won't end in a newline character because if $var ends in a
newline character, the printf output will be something like
$'...\n' or '...<actual-newline>' (so end in either single or
double quote).

> The fact that you lose the newline is, in my opinion, a pretty strong
> endorsement for having printf -v var.
> 
> arc3:~$ ksh
> h:w$ foo='newline
> > '
> h:w$ bar=$(printf %s "$foo")
> h:w$ echo "<$bar>"
> <newline>
> 
> With Bash-style printf -v bar %s "$foo" the content would have been
> copied properly.

It's really strange that no shell, not even zsh or fish fixed
that (removing all trailing newlines instead of just only one).

The usual work around is to do

var=$(cmd && echo .) && var=${var%?} && var=${var%?}
(to remove only one newline)

but that's obviously a pain.

rc is a bit more consistent and useful, the newline removing is
done as part of word splitting in `{cmd}. And you can specify
$ifs for a single cmdsubst with ``(separators){cmd} and make it
empty with ``(){cmd}. Then there's no splitting or newline
removal. But it becomes difficult to remove the one extra
newline you don't want like in:

dir = ``(){dirname -- $file}

Where you want to preserve all the newline characters in $file,
but not the one added by dirname.

es can do it like:

$ nl=$'\n' file=$'foo\nbar\n\n\n/baz' es -c '
  printf [%s]\n <={~~ ``(){dirname -- $file} *$nl}'
[foo
bar


]

But again, that's not straightforward.

Note that while I agree printf -v fixes it for printf, we'd need
to add that for every command that prints its return value
(dirname, basename, expr...). It would make more sense to fix
command substitution (or provide alternate syntax for not
removing newline, or removing only one, and also why not specify
the separators and disable globbing on the result) in the first
place.

-- 
Stephane




reply via email to

[Prev in Thread] Current Thread [Next in Thread]