Adding prefixes


bash の function で

DOMAINS="abc.tld def.tld ghi.tld ..."

という部分を

DOMAINS="host.abc.tld host.def.tld host.ghi.tld ..."

というものに置き換えたいと言うものです。

いくつかの意見で shell の問題だから comp.lang.shell に質問するべきだというものがありますが、回答として挙げられているものを示しておきます。

以下は bash 自身で環境変数を置き換えるものです。

DOMAINS=$( printf "%s\n" $DOMAINS | awk '{ printf "host.%s ", $0 }' )

また、awk は悪くはないと発言した上で、複数行で以下のようにも記述できるようです。

DOMAINS="abc.tld def.tld ghi.tld ..."
DOMAINS=$(
  awk '
    BEGIN {
      $0 = ARGV[1]
      for (i = 1; i <= NF; i++)
        $i = "host." $i
      print
      exit
    }' "$DOMAINS"
)

他の方法として、以下のようなものも挙げられています。

DOMAINS=$(
  printf '%s\n' "$DOMAINS" |
    tr -s '[:blank:]' '[\n*]' |
    sed -n 's/./host.&/p' |
    paste -sd " " -
)
IFS=" "
set -f
set -- $DOMAINS
for i; do
  set -- "$@" "host.$1"
  shift
done
DOMAINS="$*"
awk 'BEGIN{OFS=" host."}{$1=OFS $1;sub(FS,"")}9' file

上記で先頭のスペースが許されるのであれば、以下のものも使えます。

awk 'BEGIN{OFS=" host."}{$1=OFS $1}9' file
awk '{$1=(OFS=" host.")$1}9' file

この "9" は ("1" でもいいのですが) FAQ になりつつありますが、{print} と同義です。
この場合であれば、前のアクション部で置換 or $1 の再構成を行ったものが評価式ではないため、そのままでは出力されません。
そこで、出力させるために "0" 以外にしてやっているだけです。

当然、評価式にしてやればこの "9" すら不要なわけですが、それぞれ以下のようになります。

awk 'BEGIN{OFS=" host."}($1 = OFS $1) && sub(FS,"")' file
awk 'BEGIN{OFS=" host."}$1 = OFS $1' file

個人的にはこちら方が分かりやすいのですが、「アクション部の前は正規表現」と誤解している人も多いようなので、気を付けた方が良いのかもしれません。

#!/bin/sh
DOMAINS="abc.tld def.tld ghi.tld"
DOMAINS=$(echo $DOMAINS | awk 'BEGIN{RS=" "}{print "host." $0}')
echo $DOMAINS