Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash substrings and parameter expansion without assigning to a variable

Tags:

bash

shell

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.

like image 957
beroe Avatar asked Oct 02 '22 15:10

beroe


1 Answers

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.
like image 104
ghoti Avatar answered Oct 13 '22 10:10

ghoti