4

I have a script with the following variable assignment:

TEST_VARIABLE=${3#?} 

What does the ${3#?} do?

2 Answers 2

6

That is called parameter expansion:

  1. $3 is your variable, which is the third parameter of the script/function.
  2. # will remove the shortest prefix of the variable.
  3. ? is the pattern you are looking for (in this case is any character).

So basically you remove the shortest prefix of the variable named 3 until you find the pattern.

In general, we can consider:

${variable_name[option][pattern]} 

There are other options like:

  • ## remove largest prefix.
  • % remove shortest suffix.
  • %% remove largest suffix.

Which you can combine with other patterns, for example, for getting the last field of a CSV line:

> string="asdf,1234,aa,foo22" > echo ${string##*,} foo22 

Notice how we have removed the largest prefix searching for the pattern "any character(s) followed by a comma".

3
> set -- 1 2 foo > echo "$3" foo TEST_VARIABLE=${3#?} > echo "$TEST_VARIABLE" oo 

It assigns the value of the third positional parameter without its first char to the variable TEST_VARIABLE (the positional parameter itself is not changed); used in functions or shell scripts:

./myscript 1 2 foo # or myfunc 1 2 foo # within each $3 is foo 

In order to have positional parameters within an interactive shell you need set.

6
  • 1
    Why do you write "usually used in functions"? I'm at a loss to understand why you'd want to drop the first character of an argument. Commented May 28, 2014 at 16:17
  • 1
    @BruceEdiger That was bad wording indeed. I meant "You don't have that in interactive shells" but, of course, it's pretty normal in scripts, too. And I have no idea either why someone should use this code. Commented May 28, 2014 at 16:23
  • 2
    @BruceEdiger - could be just a sloppy means of removing a leading -dash? Still, it's impossible to judge without the code. By the way, though, it doesn't actually drop the first character of the positional parameter - it expands without it. So set -- one two three ; echo "${3#?}" "$3" gets you hree and three. You don't lose anything - it's still there. You'd have to set -- to clear the args. Commented May 28, 2014 at 23:50
  • @BruceEdiger - I wrote this other answer today about argument mangling and it reminded me of your comment about dropping a character from an argument. I do at least that several times over in this little function and I feel it's justified. Am I crazy? unix.stackexchange.com/a/132447/52934 Commented May 31, 2014 at 0:08
  • 1
    @mikeserv - your code doesn't look crazy to me. If you need to remove the first character of a variable's value, that's one way of doing it. The "${3#?}" usage seems to hide what it's doing, rather than make it explicit. Commented May 31, 2014 at 20:02

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.