Linux gurus don’t use cut, awk, and sed when they want to replace or strip out a portion if a variable. They use parameter substitution. You can learn parameter substitution in less than 2 minutes. Here is the ten things you need to know:

  1. Shell variables can be specified like $var or this ${var}.
    $ var='a.ads,fssd2342%asd234#@.,&%,sdfgsdfgas4352'
    echo ${var}
    a.ads,fssd2342%asd234#@.,&%,sdfgsdfgas4352
  2. ${#var} is the length of the variable.
    $ echo ${#var}
    42
  3. ${var:pos} substrings the variable starting at pos.
    $ echo ${var:10}
    2342%asd234#@.,&%,sdfgsdfgas4352
  4. ${var:pos:len} substrings the variable starting at pos with a max length of len.
    $ echo ${var:10:5}
    2342%
  5. ${var#pattern} strips pattern from the front or left hand side of the variable. This form is not greedy meaning it stops as soon as the pattern is matched. ${var##pattern} is the greedy form.
    $ echo ${var#*,}
    fssd2342%asd234#@.,&%,sdfgsdfgas4352
    $ echo ${var##*,}
    sdfgsdfgas4352
  6. ${var%pattern} strips pattern from the back or right hand side of the variable. This form is not greedy meaning it stops as soon as the pattern is matched. ${var%%pattern} is the greedy form.
    $ echo ${var%,*}
    a.ads,fssd2342%asd234#@.,&%
    $ echo ${var%%,*}
    a.ads
  7. ${var/pattern/replacement} replaces pattern with replacement once.
    $ echo ${var/a/A}
    A.ads,fssd2342%asd234#@.,&%,sdfgsdfgas4352
  8. ${var//pattern/replacement} replaces pattern with replacement globally.
    $ echo ${var//a/A}
    A.Ads,fssd2342%Asd234#@.,&%,sdfgsdfgAs4352
  9. ${var/#pattern/replacement} if variable beginning matches the pattern it is replaced with replacement.
    $ echo ${var/#a./llll}
    llllads,fssd2342%asd234#@.,&%,sdfgsdfgas4352
  10. ${var/%pattern/replacement} if variable end matches the pattern it is replaced with replacement.
    $ echo ${var/%352/llll}
    a.ads,fssd2342%asd234#@.,&%,sdfgsdfgas4llll

29 Responses to “10 Steps to Beautiful Shell Scripts”

  1. roko Says:

    Excellent ! thanks a lot !

  2. Dave Says:

    I’ll make good use of some of these…
    There’s a typo at No.5 though, it should be a curly brace not a parenthesis, I only noticed this because I’ve printed this out to look at again later.

  3. admin Says:

    Woops, your right. I’ll fix that. Thanks!

  4. Joe Says:

    Hmmm, seems cool.

    Joe joestain13@yahoo.com

  5. Rodrigo Urubatan Says:

    Cool :D
    but I think at least for now, I’ll stick with cut and awk because I like to read what I wrote last week :D

  6. admin Says:

    It definitely takes some getting used to.

  7. Matt Says:

    Very nice – I love Bash and have written many smaller shell scripts. This is a most useful reference.

  8. Andrei Says:

    Sweet, but I like to keep it more compatible with “true /bin/sh” which means that all this fancy stuff does belong to sed, awk, tr…

  9. Ozh Says:

    Wow very cool, didn’t know about this, I’m always piping through sed…

  10. Binny V A Says:

    Wow – I did not know bash was this powerful. Thanks.

  11. chris Says:

    Getting into practice with these might reduce the number of times I launch perl for some trivial text manipulations.

  12. links for 2007-10-20 « Mandarine Says:

    [...] 10 Steps to Beautiful Shell Scripts Linux gurus don’t use cut, awk, and sed when they want to replace or strip out a portion if a variable. They use parameter substitution. You can learn parameter substitution in less than 2 minutes. (tags: regex) [...]

  13. Thierry Says:

    Interesting article.
    You’ve inverted the info for greedy and non-greedy though.
    You say, for example, that ${var##pattern} is the greedy form, but then, in the example, it’s the version that returns the smallest string :
    $ echo ${var#*,}
    fssd2342%asd234#@.,&%,sdfgsdfgas4352
    $ echo ${var##*,}
    sdfgsdfgas4352

  14. admin Says:

    Thierry,

    The single # stops when it finds the shortest match. The double ## stops when it finds the longest match. Thus the double ## is described as “greedy”. Here is another example:


    $ v='1,2,3,4'
    $ echo ${v#*,}
    2,3,4
    $ echo ${v##*,}
    4

  15. Chris F.A. Johnson Says:

    “Sweet, but I like to keep it more compatible with “true /bin/sh” which means that all this fancy stuff does belong to sed, awk, tr…”

    Which “true /bin/sh” are you referring to? A true Bourne shell? Or a standard UNIX/POSIX shell?

    It has been many years since a *nix system came without a POSIX shell, which includes some of the expansions in the article. On many, if not most *nix systems, /bin/sh is a POSIX shell; the others have a POSIX shell tucked away somewhere.

    These three articles describe the Bourne expansions, POSIX expansions, and the extended expansions in ksh93 and bash:

    http://wiki.ittoolbox.com/index.php/Parameter_expansions

    http://wiki.ittoolbox.com/index.php/POSIX_shell_expansions

    http://wiki.ittoolbox.com/index.php/Extended_parameter_expansions

  16. Richard Says:

    Parameter substitution is truly a remarkable thing. The other night, I was trying to get the ‘rename’ function to alter the *start* of a group of filenames, to no avail. I’m renaming files, so I should use rename, right?

    Then, I thought, “why am I doing this?”

    Solved with,
    for file in *
    do
    mv $file ${file/#somestring/someotherstring}
    done

    All too easy…

  17. Ryan Roth Says:

    Thanks for this tip. I have been looking for something like this for years and never knew it existed. This is so much cleaner than sed for so many of my daily tasks.

  18. nitin Says:

    Please also include variable substitutions like
    ${var:?”message”}-That prints message if varible does not exist,${var:-word},…

  19. Creating patches and my core dump patch for Apache 2 Peruser MPM Says:

    [...] If your interested on why I had to create a patch, read on. Otherwise you may be interested in an older post 10 Steps to Beautiful Shell Scripts. [...]

  20. Keeping your SSH sessions alive with NOOP Says:

    [...] a random number using the special variable $RANDOM. This random is assigned to the variable num, utilizing only the first digit. After printing that number, the script sleeps num tenths of seconds, and the backspace function is [...]

  21. Shounak Says:

    Very informative.
    I have been working as a Linux Admin for almost a year now. Found this info very interesting.
    Some more pages like this and we will have superb BASH scripts coming from everyone.
    Great post !

    Thanks

  22. Sree Says:

    superb

  23. Root Says:

    I guess one of the mistakes we all make at the beginning is using the wrong tool for the job because we do not yet know what else is available. I have been abusing sed for a while now and getting frustrated with it. Once I found out about parameter substitution I was much happier. :)

  24. Karthik Says:

    Thanks! I was trying to understand a shell script which was written by an expert and he had extensively used these things. Searched a lot and finally got ur article. I can understand the script easily now.

    Thanks once again
    Karthik

  25. Deepankar Says:

    What if we have a long record with all fiels as pipe seperated?
    eg:
    abc|def1|ghi2|jkl3|mno4|pqr5|stu6|vwx7

    Here if i need to extract the 5th field, is there a way to do this using parameter substitution in a variable (supposing I initialize the variable with the content of the record mentioned above?

    Any way this was a nice thing to learn and it will take some time to master it.

    regards

  26. de.straba.us » Blog Archive » Bash shell in 30″ Says:

    [...] http://bashcurescancer.com/10-steps-to-beautiful-shell-scripts.html [...]

  27. pitsch Says:

    > “true /bin/sh”
    In BusyBox v1.1.3 examples 1,2,5 are working.

  28. Being Greedy With Bash Says:

    [...] cannot search Google for special characters, I Googled “Bash greedy” and luckily found 10 Steps to Beautiful Shell Scripts, which just so happened to contain the technique I was looking for [...]

  29. Samba Says:

    It is really helpful, thanks a lot

Leave a Reply

If Wordpress eats your comment (shell output, loops, ex..) email the text to me.