bash: case and command substitution--what gives?
I've been trying to embed a simple filtering statement into another command, but I keep getting a syntax error.
I start with something like this to grab files with a specified extension $ext: Code:
for i; do Code:
files=$( However, I can change the case structure to something else, like: Code:
files=$( So why doesn't case work here? What am I overlooking? |
Hi.
The ')' in the case statement is matching the '(' from files=$( Try using files=`blah blah blah` instead of files=$(blah blah blah) Dave |
Well, whaddaya know. That works. I hadn't thought about trying the backticks.
But I had considered the idea that the ')' was causing it. I decided that that couldn't be it, however, because I can surround it with parentheses to create a subshell. Code:
(for i; do |
Here is the way your original code should be written:
Code:
files=$( |
What, you can do that? I've never seen anything anywhere that said you could completely enclose the matching conditions in a case construct.
In any case, could this be a bug? I'd certainly consider it one. I don't think it should be necessary to materially alter the syntax of the commands inside of $(), particularly if it's not well-documented. Edit: Did a little google searching, now that I know what's going on. Apparently it's a long-standing bug that's difficult to handle at the compiler level. And that appears to be the reason the fully-enclosed tests were introduced. It would be nice if it were better-documented though. At least the ABSG could've mentioned it. :( Edit two: This page has a chart that lists which shells can and can't handle various "unbalanced" parentheses statements inside $(). |
I wouldn't tell it's a shell bug as it was identified when the $() syntax was introduced by the korn shell a couple of decade ago, just a well known incompatibility between an old syntax and a newer one with a documented workaround.
I have been using the extra left parenthesis in all my case/esac statements for ages. It looks to me neater and more convenient than the original unbalanced design anyway. Despite being accepted by the standard, the newer shells accepting unbalanced parenthesis looks an ugly hack to me. It is worth noticing the backquote syntax was considered as archaic in 1992 in the ksh documentation but is still widely used nowadays. |
Got a follow-up to this topic.
Debian has just included Bash v.4 in it's repositories (at least in unstable), and now the problem is gone. :) They've fixed this little error. I did come across some new problems, however. One of my scripts uses an embedded here document, and it started spitting out an error after the upgrade. I was using something like this: Code:
output=$(cat <<-FOOBAR Unfortunately though, there also seems to be a new, different bug. Any and all trailing newlines, in any kind of text output, now appear to be removed when inside $(). They not only disappear in the above code, but even when using something like echo. Code:
#!/bin/bash I suppose I'll have to switch to using functions for generating large, formatted blocks of text instead. :) All in all, though, bash 4 does seem to have some neat new features. I'm looking forward to playing with them. |
These aren't two new bugs but actually two bug fixes.
Both removing trailing newlines and having the here document alone in its line are requirement to comply with the POSIX standard. Quoted from http://www.opengroup.org/onlinepubs/...cu_chap02.html The shell shall expand the command substitution by executing command in a subshell environment (see Shell Execution Environment) and replacing the command substitution (the text of command plus the enclosing "$()" or backquotes) with the standard output of the command, removing sequences of one or more <newline>s at the end of the substitution. |
Thank you for that information. To be fair, I didn't say that the first one was a bug, only that the behavior was different than before.
The removing all trailing newlines thing is a bit annoying though. It's my opinion that command substitution should, you know, substitute, the complete output of the embedded commands, no matter what they contain. Editing shouldn't be part of the process, even if it's just a few extra newlines. It should be up to the scripter to ensure that the substitution produces the desired output. I was used to depending on the former behavior. Now I'm going to have to rewrite a couple of my old scripts. :( |
Yes, I agree that can be annoying. Actually, I'm missing what the rationale might be about removing trailing newlines. :scratch:
|
All times are GMT -5. The time now is 09:03 AM. |