• Uncategorized

About bash : Add-prefix-and-suffix-to-in-bash

Question Detail

How to add suffix and prefix to [email protected]?

If I do $PREFIX/[email protected]/$SUFFIX, I get the prefix and the suffix only in the first parameter.

Question Answer

I would use shell [ parameter expansion ] for this

$ set -- one two three
$ echo "[email protected]"
one two three
$ set -- "${@/#/pre}" && set -- "${@/%/post}"
$ echo "[email protected]"
preonepost pretwopost prethreepost

Notes

  • The # matches the beginning
  • The % matches the end
  • Using double quotes around ${@} considers each element as a separate word. so replacement happens for every positional parameter

Let’s create a parameters for test purposes:

$ set -- one two three
$ echo "[email protected]"
one two three

Now, let’s use bash to add prefixes and suffixes:

$ IFS=$'\n' a=($(printf "pre/%s/post\n" "[email protected]"))
$ set -- "${a[@]}"
$ echo -- "[email protected]"
pre/one/post pre/two/post pre/three/post

Limitations: (a) since this uses newline-separated strings, it won’t work if your [email protected] contains newlines itself. In that case, there may be another choice for IFS that would suffice. (b) This is subject to globbing. If either of these is an issue, see the more general solution below.

On the other hand, if the positional parameters do not contain whitespace, then no change to IFS is needed.

Also, if IFS is changed, then one may want to save IFS beforehand and restore afterward.

More general solution

If we don’t want to make any assumptions about whitespace, we can modify “[email protected]” with a loop:

$ a=(); for p in "[email protected]"; do a+=("pre/$p/post"); done
$ set -- "${a[@]}"
$ echo "[email protected]"
pre/one/post pre/two/post pre/three/post

Note: This is essentially a slightly more detailed version of sjam’s answer.

John1024’s answer is helpful, but:

  • requires a subshell (which involves a child process)
  • can result in unwanted globbing applied to the array elements.

Fortunately, Bash parameter expansion can be applied to arrays too, which avoids these issues:

set -- 'one' 'two' # sample input array, which will be reflected in [email protected]

# Copy [email protected] to new array ${a[@]}, adding a prefix to each element.
# `/#` replaces the string that follows, up to the next `/`,
# at the *start* of each element.
# In the absence of a string, the replacement string following
# the second `/` is unconditionally placed *before* each element.
a=( "${@/#/PREFIX}" )

# Add a suffix to each element of the resulting array ${a[@]}.
# `/%` replaces the string that follows, up to the next `/`,
# at the *end* of each element.
# In the absence of a string, the replacement string following
# the second `/` is unconditionally placed *after* each element.
a=( "${a[@]/%/SUFFIX}" )

# Print the resulting array.
declare -p a

This yields:

declare -a a='([0]="PREFIXoneSUFFIX" [1]="PREFIXtwoSUFFIX")'

Note that double-quoting the array references is crucial to protect their elements from potential word-splitting and globbing (filename expansion) – both of which are instances of shell expansions.

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.