Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bash string manipulation cheatsheet.

Bash string manipulation cheatsheet

Assignment
Assign value to variable if variable is not already set, value is returned.

Combine with a : no-op to discard/ignore return value.
${variable="value"}
: ${variable="value"}
Removal
Delete shortest match of needle from front of haystack ${haystack#needle}
Delete longest match of needle from front of haystack ${haystack##needle}
Delete shortest match of needle from back of haystack ${haystack%needle}
Delete longest match of needle from back of haystack ${haystack%%needle}
Replacement
Replace first match of needle with replacement from haystack ${haystack/needle/replacement}
Replace all matches of needle with replacement from haystack ${haystack//needle/replacement}
If needle matches front of haystack replace with replacement ${haystack/#needle/replacement}
If needle matches back of haystack replace with replacement ${haystack/%needle/replacement}
Substitution
If variable not set, return value, else variable ${variable-value}
If variable not set or empty, return value, else variable ${variable:-value}
If variable set, return value, else null string ${variable+value}
If variable set and not empty, return value, else null string ${variable:+value}
Extraction
Extract length characters from variable starting at position ${variable:position:length}
String length of variable ${#variable}

Reference

@chb0github

This comment has been minimized.

Copy link

chb0github commented Feb 22, 2019

I'd like to propose a few additions

${variable##*.} -> returns everything after the last . in a string. Handy for getting file extensions

variable="/Users/cbongiorno/rds.json"
echo ${variable##*.}
json

Remove the last character from a string:

echo ${variable%%?}
/Users/cbongiorno/rds.jso

Remove the first character from a string:

echo ${variable##?}
Users/cbongiorno/rds.json
@magnetikonline

This comment has been minimized.

Copy link
Owner Author

magnetikonline commented Feb 22, 2019

Nice one @chb0github 👍

The last/first char drops can be extended by padding out the ? count too - works nicely.

@vsoch

This comment has been minimized.

Copy link

vsoch commented Apr 12, 2019

Maybe you can make this into a repo so others can PR with said additions?

@BobDodds

This comment has been minimized.

Copy link

BobDodds commented Aug 31, 2019

Regex for these string manipulation functions seems to have its own unique standard, not regular or extended like sed and [[ ]]. Where is that cheatsheet?

@magnetikonline

This comment has been minimized.

Copy link
Owner Author

magnetikonline commented Sep 2, 2019

@BobDodds these methods/functions don't support Regular Expressions. They are effectively glob like patterns, like * and . - sadly not a full regexp implement/engine.

Examples are here: http://tldp.org/LDP/abs/html/string-manipulation.html

@BobDodds

This comment has been minimized.

Copy link

BobDodds commented Sep 2, 2019

@magnetikonline Thank you yes I found where it is explained that if we have shellopt extglob on, then we have a regex-like power but not a BASH_REMATCH or sed extended regex and \1 \2 etc to use in the right hand of ${string/x(y)x/z\1z/}.

Example. and extglob works like this:

      ?(pattern-list)
             Matches zero or one occurrence of the given patterns
      *(pattern-list)
             Matches zero or more occurrences of the given patterns
      +(pattern-list)
             Matches one or more occurrences of the given patterns
      @(pattern-list)
             Matches one of the given patterns
      !(pattern-list)
             Matches anything except one of the given patterns

"extglob implements a subset of ksh extended globs. ksh93 actually has a printf operator to convert between patterns and (AT&T) REs (printf '%P\n' '\[[0-9]\]' gives \[([0-9])\]) – Stéphane Chazelas Aug 28 '13 at 10:03
Hmm, it seems that *[0-9] works in other regex queries (without round brackets). – macieksk Jan 22 at 22:27"

@BobDodds

This comment has been minimized.

Copy link

BobDodds commented Sep 2, 2019

One more thing that we can do...

string=abcdeff ; echo ${string/#a/} ${string/%f/} ${string/%f*/}
bcdeff abcdef abcde

...so weird the "#" working as expected as synonym for '^' in extended regex, but so weirdly the "%" coming before the "f" to glob the same as '$' in sed -E extended regex

@magnetikonline

This comment has been minimized.

Copy link
Owner Author

magnetikonline commented Sep 2, 2019

Thanks for that @BobDodds - going over that voodoo, you can excuse me if I decide to avoid that going forward 😄 - my brain can only handle/hold the workings of Regexp!

@BobDodds

This comment has been minimized.

Copy link

BobDodds commented Sep 3, 2019

# is for hopscotch at the ground level = beginning.

% is for mickey mouse ears on top = end.

Mickey Mouse club, cult, voodoo: ${string/%f*/} like % is a weird internal func %(){THE END;} which is mickey_mouse_ears() {garbage;}

I may need to meditate on that with my legs crossed like the optic nerve makes an X like #, behind the two eyeballs like % with a nose in the middle. That's not helping. I should just know Y.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.