zsh-workers
 help / color / mirror / code / Atom feed
* b='${a//"/}' and ${(e)b}
@ 2008-05-10 12:38 Stephane Chazelas
  2008-05-10 17:12 ` Bart Schaefer
  2008-05-10 21:02 ` [PATCH] zmv (Was: b='${a//"/}' and ${(e)b}) Stephane Chazelas
  0 siblings, 2 replies; 4+ messages in thread
From: Stephane Chazelas @ 2008-05-10 12:38 UTC (permalink / raw)
  To: Zsh hackers list

Hiya,

$ a='a"b'
$ b='${a//"/}'
$ echo ${(e)b}

$ b='${a//\"/}'
$ echo ${(e)b}

$ b='${a//\\"/}'
$ echo ${(e)b}

$ b='${a//\\\"/}'
$ echo ${(e)b}

$ b='${a//["]/}'
$ echo ${(e)b}

$ b='${a//[a]/}'
$ echo ${(e)b}
"b
$ echo "${a//"/}"
dquote braceparam>
$ echo "${a//\"/}"
ab
$ b='${a//["]/}'
$ echo ${(eq)b}
$\{a//\[\"\]/\}
$ echo ${(qe)b}
$\{a//\[\"\]/\}

How would I do?

I came accross the problem when trying:

zmv '*"*' '${f//"/}'
[...]
+zmv:42> pat='*"*'
+zmv:43> repl='${f//"/}'
+zmv:44> shift 2
+zmv:45> [[ -z '' ]]
+zmv:47> tmpf=/tmp/zshzmv5557
+zmv:48> print -P %N
+zmv:49> myname=zmv
+zmv:50> rm -f /tmp/zshzmv5557
+zmv:51> action=mv
+zmv:52> [[ mv != '(cp|mv|ln)' ]]
+zmv:58> [[ -n '' ]]
+zmv:63> [[ -n '' || -n '' ]]
+zmv:91> [[ -n '' ]]
+zmv:96> [[ '*"*' == '(#b)(*)((**##/))(*)' ]]
+zmv:107> fpat='*"*'
+zmv:109> files=( 'a"' )
+zmv:110> [[ -n '' ]]
+zmv:111> errs=( )
+zmv:112> f=a"
+zmv:114> [[ '*"*' == '(#b)(*)(**##/)(*)' ]]
+zmv:118> [[ -e 'a"' && 'a"' == '(#b)*"*' ]]
+zmv:119> set -- ''
g=${(e)repl} +zmv:120> g=''
+zmv:121> [[ -z '' ]]
+zmv:123> errs=( '`a"'\'' expanded to an empty string' )
+zmv:135> from[$g]='a"'
+zmv:136> to[$f]=''
+zmv:138> ((  1  ))
+zmv:140> print -P '%N: error(s) in substitution:'
zmv: error(s) in substitution:
+zmv:141> print -l '`a"'\'' expanded to an empty string'
`a"' expanded to an empty string
+zmv:142> return 1

BTW, shouldn't it be "print -rl -- $errs >&2"?

And -r added to all those "print"s?

It might be a good idea also to use some ${(V)var} when
stdout/stderr is a tty.

Best regards,
Stéphane


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: b='${a//"/}' and ${(e)b}
  2008-05-10 12:38 b='${a//"/}' and ${(e)b} Stephane Chazelas
@ 2008-05-10 17:12 ` Bart Schaefer
  2008-05-11 16:10   ` Stephane Chazelas
  2008-05-10 21:02 ` [PATCH] zmv (Was: b='${a//"/}' and ${(e)b}) Stephane Chazelas
  1 sibling, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2008-05-10 17:12 UTC (permalink / raw)
  To: Zsh hackers list

On May 10,  1:38pm, Stephane Chazelas wrote:
}
} $ a='a"b'
} $ b='${a//"/}'
} $ echo ${(e)b}

(etc.)

If you use

$ echo ${(Xe)b}

Then you'll see that zsh burps "parse error" on nearly every one of those
expressions.  Without the (X) flag the error is silently ignored and the
expansion returns nothing.  (Perhaps zmv should use (X).)

Now, as to why it's hard to quote a double quote within a // replacement
when using the (e) flag, I'm not sure what to say except that the parsing
rules for all those nested levels of sometimes-implicit quoting get a bit
arcane.

} How would I do?

$ c='"'
$ b='${a//$c/}'
$ print ${(Xe)b}

Which does work for zmv:

$ zmv -n '*"*' '${f//$c/}'
mv -- a\"b ab

Or you can do this:

$ zmv -n '*"*' '$f:gs/"//'
mv -- a\"b ab

The parsing rules for :s are a lot simpler than those for ${...}.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] zmv (Was: b='${a//"/}' and ${(e)b})
  2008-05-10 12:38 b='${a//"/}' and ${(e)b} Stephane Chazelas
  2008-05-10 17:12 ` Bart Schaefer
@ 2008-05-10 21:02 ` Stephane Chazelas
  1 sibling, 0 replies; 4+ messages in thread
From: Stephane Chazelas @ 2008-05-10 21:02 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1302 bytes --]

While I was looking at zmv:

I read:

if [[ -z $action ]]; then
  # We can't necessarily get the name of the function directly, because
  # of no_function_argzero stupidity.
  tmpf=${TMPPREFIX}zmv$$
  print -P %N >$tmpf
  myname=$(<$tmpf)
  rm -f $tmpf

  action=$myname[-2,-1]

  if [[ $action != (cp|mv|ln) ]]; then
    print "Action $action not recognised: must be cp, mv or ln." >&2
    return 1
  fi
fi

We could use:

action=${(%):-%N}
(which looks like a very complicated smiley)

Also, for tempfiles, there's

tmpf==(print -P %N)

Also, I read:

print -P "%N: unrecognized option: -$OPTARG" >&2

If $OPTARG is "%", that fails 

Maybe it would make sense to have a %P as a printf format for
prompt expansions:

printf '%P: unrecognized option: -%s\n' %N "$OPTARG"

Of course, the above can be written:

print -nP %N >&2
print -r ": unrecognized option: -$OPTARG" >&2

or

print -r "${(%):-%N}: unrecognized option: -$OPTARG" >&2

though

Also, I've seen some problems with the: $find variable:

$ zmv -wn '[a\\]' '$f'
zmv: warning: no wildcards were found in search pattern
$ zmv -wn 'a#' '$f'
zmv: warning: no wildcards were found in search pattern

Please find a patch attached.

Please test as I'm not really confident that I didn't introduce
a few pairs of half-dozens bugs ;)

-- 
Stéphane

[-- Attachment #2: diff --]
[-- Type: text/plain, Size: 3471 bytes --]

Index: zmv
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Misc/zmv,v
retrieving revision 1.13
diff -u -r1.13 zmv
--- zmv	13 Apr 2008 16:11:54 -0000	1.13
+++ zmv	10 May 2008 20:59:45 -0000
@@ -128,12 +128,14 @@
 typeset -A from to
 integer stat
 
+myname=${(%):-%N}
+
 while getopts ":o:p:MCLfinqQsvwW" opt; do
   if [[ $opt = "?" ]]; then
-    print -P "%N: unrecognized option: -$OPTARG" >&2
+    print -r -- "$myname: unrecognized option: -$OPTARG" >&2
     return 1
   fi
-  eval "opt_$opt=${(q)OPTARG:--$opt}"
+  eval "opt_$opt=\${OPTARG:--\$opt}"
 done
 (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
 
@@ -143,6 +145,15 @@
 [[ -n $opt_L ]] && action=ln
 [[ -n $opt_p ]] && action=$opt_p
 
+if [[ -z $action ]]; then
+  action=$myname[-2,-1]
+
+  if [[ $action != (cp|mv|ln) ]]; then
+    print -r "$myname: action $action not recognised: must be cp, mv or ln." >&2
+    return 1
+  fi
+fi
+
 if (( $# != 2 )); then
   print -P "Usage:
   %N [OPTIONS] oldpattern newpattern
@@ -164,25 +175,8 @@
 repl=$2
 shift 2
 
-if [[ -z $action ]]; then
-  # We can't necessarily get the name of the function directly, because
-  # of no_function_argzero stupidity.
-  tmpf=${TMPPREFIX}zmv$$
-  print -P %N >$tmpf
-  myname=$(<$tmpf)
-  rm -f $tmpf
-
-  action=$myname[-2,-1]
-
-  if [[ $action != (cp|mv|ln) ]]; then
-    print "Action $action not recognised: must be cp, mv or ln." >&2
-    return 1
-  fi
-fi
-
-
 if [[ -n $opt_s && $action != ln ]]; then
-  print -P "%N: invalid option: -s" >&2
+  print -r -- "$myname: invalid option: -s" >&2
   return 1
 fi
 
@@ -193,10 +187,10 @@
   # Well, this seems to work.
   # The tricky bit is getting all forms of [...] correct, but as long
   # as we require inactive bits to be backslashed its not so bad.
-  find='(#m)(\*\*#[/]|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##'
+  find='(#m)((\*\*#/|[*?]|<[0-9]#-[0-9]#>|\[(^|)(\]|)(\[:[a-z]##:\]|\\?|[^\]])##\])\##|?\###)'
   tmp="${pat//${~find}/$[++cnt]}"
   if [[ $cnt = 0 ]]; then
-    print -P "%N: warning: no wildcards were found in search pattern" >&2
+    print -r -- "$myname: warning: no wildcards were found in search pattern" >&2
   else
     pat="${pat//${~find}/($MATCH)}"
   fi
@@ -252,26 +246,33 @@
   fi
   [[ -e $f && $f = (#b)${~pat} ]] || continue
   set -- "$match[@]"
-  g=${(e)repl}
+  { {
+    g=${(Xe)repl}
+  } 2> /dev/null } always {
+    if (( TRY_BLOCK_ERROR )); then
+      print -r -- "$myname: syntax error in replacement" >&2
+      return 1
+    fi
+  }
   if [[ -z $g ]]; then
-    errs=($errs "\`$f' expanded to an empty string")
+    errs+=("\`$f' expanded to an empty string")
   elif [[ $f = $g ]]; then
     # don't cause error: more useful just to skip
     #   errs=($errs "$f not altered by substitution")
-    [[ -n $opt_v ]] && print "$f not altered, ignored"
+    [[ -n $opt_v ]] && print -r -- "$f not altered, ignored"
     continue
   elif [[ -n $from[$g] && ! -d $g ]]; then
-    errs=($errs "$f and $from[$g] both map to $g")
+    errs+=("$f and $from[$g] both map to $g")
   elif [[ -f $g && -z $opt_f && ! ($f -ef $g && $action = mv) ]]; then
-    errs=($errs "file exists: $g")
+    errs+=("file exists: $g")
   fi
   from[$g]=$f
   to[$f]=$g
 done
 
 if (( $#errs )); then
-  print -P "%N: error(s) in substitution:" >&2
-  print -l $errs >&2
+  print -r -- "$myname: error(s) in substitution:" >&2
+  print -lr -- $errs >&2
   return 1
 fi
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: b='${a//"/}' and ${(e)b}
  2008-05-10 17:12 ` Bart Schaefer
@ 2008-05-11 16:10   ` Stephane Chazelas
  0 siblings, 0 replies; 4+ messages in thread
From: Stephane Chazelas @ 2008-05-11 16:10 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

On Sat, May 10, 2008 at 10:12:41AM -0700, Bart Schaefer wrote:
[...]
> } $ a='a"b'
> } $ b='${a//"/}'
> } $ echo ${(e)b}
> 
> (etc.)
> 
> If you use
> 
> $ echo ${(Xe)b}
> 
> Then you'll see that zsh burps "parse error" on nearly every one of those
> expressions.  Without the (X) flag the error is silently ignored and the
> expansion returns nothing.  (Perhaps zmv should use (X).)
> 
> Now, as to why it's hard to quote a double quote within a // replacement
> when using the (e) flag, I'm not sure what to say except that the parsing
> rules for all those nested levels of sometimes-implicit quoting get a bit
> arcane.
> 
> } How would I do?
> 
> $ c='"'
> $ b='${a//$c/}'
> $ print ${(Xe)b}
> 
> Which does work for zmv:

Hi Bart,

yes, that's what I had eventually found out as well (here's the
comp.unix.shell discussion that started it:
http://groups.google.com/group/comp.unix.shell/msg/df86a6f26b8ed168)

I now also find that

b='${a//"\""/}'

works.

That doesn't sound quite right though.

-- 
Stéphane


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-05-11 16:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-10 12:38 b='${a//"/}' and ${(e)b} Stephane Chazelas
2008-05-10 17:12 ` Bart Schaefer
2008-05-11 16:10   ` Stephane Chazelas
2008-05-10 21:02 ` [PATCH] zmv (Was: b='${a//"/}' and ${(e)b}) Stephane Chazelas

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).