3

This is an example function:

function example { echo "TextBefore $@ TextAfter" ; }

This is the command using the function:

example A{1..5}B

The output:

TextBefore A1B A2B A3B A4B A5B TextAfter

How I want it to be:

TextBefore A1B TextAfter
TextBefore A2B TextAfter
TextBefore A3B TextAfter
TextBefore A4B TextAfter
TextBefore A5B TextAfter

That's as good as I can describe it. If you understand it and know a better way of describing it, please edit the question.

How can I make each [insert word here] in the sequence being executed separately, as shown in that example?

neverMind9
  • 1,690

3 Answers3

10

Try this:

function example { printf 'TextBefore %s TextAfter\n' "$@"; }
Freddy
  • 25,565
5

Use printf rather than echo. The printf utility takes a format string as its first argument (which can always be a single quoted string), and this string would contain a placeholder for your other arguments:

printf 'TextBefore %s TextAfter\n' "$@"

The arguments in "$@" would be inserted in the position given by %s. Since there is only one %s placeholder in the format string, the format string will be reused for each argument in turn. This is different from how printf works in other languages.

Note that printf does not output a terminating newline by default.

Example:

$ printf 'AAA %s BBB\n' 1 2 3 4 5
AAA 1 BBB
AAA 2 BBB
AAA 3 BBB
AAA 4 BBB
AAA 5 BBB

If there are more placeholders in the formatting string, these will be filled in turn by the arguments given to printf. The formatting string will be reused when all placeholders have been filled if there are still more arguments available.

$ printf 'AAA %s %03d BBB\n' 1 2 3 4 5
AAA 1 002 BBB
AAA 3 004 BBB
AAA 5 000 BBB

Your function may therefore look like

example () {
    [ "$#" -gt 0 ] && printf 'TextBefore %s TextAfter\n' "$@"
}

See also:

Kusalananda
  • 333,661
3

While both answers assume that the OP just wants to print the arguments, it may be the case that they want to pass the bracketed arguments to other command than echo or printf.

The shell has no mapcar, etc[1] so the only way is a trivial loop (replace the cmd placeholder with the actual command):

function example { for arg; do cmd "TextBefore $arg TextAfter"; done; }

As a sidenote, in the original echo "TextBefore $@ TextAfter", when called with $@ set to a A1B, A2B, ..., A5B, the separate arguments passed to echo will TextBefore A1B, A2B, ..., A5B TextAfter. That's one case where using $@ hardly makes sense.

[1] there's xargs, but navigating through xargs' pitfalls and shortcomings is not worth the trouble in such a simple case.