6

UPDATE 2: This question is related to this question, possibly because the underlying reasons why this might/might not work are the same. But I am not sure whether it is actually a duplicate, because nesting is just one example of how to get a string in there. The same basic question could also be rephrased as:

  • Is there a way to use a string directly in parameter expansion, possibly using expr
  • What would be the most concise way to pipe output to a parameter expansion?

More examples of "fake" syntax to illustrate these goals...

${$(echo "b"; b="ABCDE")::3}  #  Assign output inside?
... | grep -o "ABCDE" | ${-::2}   #  pipe to placeholder inside?

So depending on your goals, it may be a dupe or not. Anyway, from the current answers, it sounds like it is not possible anyway with this kind of approach...


This is a general question about bash operations, rather than trying to get a specific string subser...

I know you can use parameter expansion and other tricks to extract or substitute parts of a defined variable.

For example:

$ MYVAR=$(date)    # just to generate text; could be "ABCDE"
$ echo $MYVAR
Mon Oct 20 15:55:07 PDT 2014
$ echo ${MYVAR:11}
15:55:07 PDT 2014
$ echo ${MYVAR%:*}
Mon Oct 20 15:55

What I would like is a way to "nest" these operations without creating the intermediate variable.

For example, what you get when you do:

$ TIME=${MYVAR:11}
$ echo ${TIME%:*}
    15:55

I want to be able to nest the operation that is happening with TIME inside the operation that is happening on MYVAR.

The potential syntax that comes to mind is something like $() that let's you nest operations, but do it for variables. It might look something like this... (which doesn't work -- I've tried!)

echo ${`${MYVAR:11}`%:*}     # ERROR

The advantage would be that you could dispense with assigning MYVAR and TIME altogether, and use a string or $(date) (or the output of a grep, etc) in its place.

Community
  • 1
  • 1
beroe
  • 11,784
  • 5
  • 34
  • 79
  • possible duplicate of [Nested Shell Parameter Expansion](http://stackoverflow.com/questions/6724056/nested-shell-parameter-expansion) – Graham Oct 21 '13 at 03:48
  • Thanks @Graham. That question also points to another set of answers that I didn't unearth. – beroe Oct 21 '13 at 06:09
  • 1
    `bash` doesn't chain parameter expansions in this way. `foo` in `${foo...}` must be a literal name; no other expression is allowed. Some shells (notably `zsh`) do allow such chained expansions. – chepner Oct 21 '13 at 12:52

2 Answers2

3

First off, if you're really trying to parse the date, you should know that you can get precisely the date format you want from the date command itself:

$ read year month day < <(date '+%Y %m %d')
$ echo "year=$year month=$month day=$day"
year=2013 month=10 day=20

If you're using Linux, man date for formatting details. In other operating systems (FreeBSD, OSX, etc), the date command is a wrapper for the strftime() function, so you can read the man page for that instead.

That said, you don't necessarily need to use the date command to get a date in bash. If your bash version is 4+, you can printf date formats without spawning an external tool:

$ read year month day < <(printf '%(%Y %m %d)T')

But to answer your question, you can in zsh, but not in bash, ksh or other Bourne shells. The standard way of handling this is to use temporary variables, but note that you can recycle your existing variable.

$ foo="Hello world."
$ foo="${foo//l/}"; echo "$foo"
Heo word.
$ foo="${foo:4}"; echo "$foo"
word.
ghoti
  • 45,319
  • 8
  • 65
  • 104
  • Thanks Fish. Yep I know about the `date` flags. That was just to generate a string. I should edit the question to just say `"ABCDE"` Recycling vars is good. Re `zsh` I guess I should consider it, but I'd prefer sticking to bash for a couple reasons. – beroe Oct 21 '13 at 00:09
2

You can use BASH arrays and cut down temporary variable creations like this:

$ MYVAR=($(date))
$ echo "${MYVAR[@]}"
Mon Oct 20 15:55:07 PDT 2014

# get 4th elements and substring in SINGLE operation 
$ echo "${MYVAR[3]%:*}"
15:55
anubhava
  • 761,203
  • 64
  • 569
  • 643