1

I have a file template.txt and its content is below:

param1=${1}
param2=${2}
param3=${3}

I want to replace ${1},{2},${3}...${n} string values by elements of scriptParams variable.

The below code, only replaces first line.

scrpitParams="test1,test2,test3"

cat template.txt | for param in ${scriptParams} ; do i=$((++i)) ; sed -e "s/\${$i}/$param/" ; done

RESULT:

param1=test1
param2=${2}
param3=${3}

EXPECTED:

param1=test1
param2=test2
param3=test3

Note: I don't want to save replaced file, want to use its replaced value.

3 Answers3

1

Learn to debug:

cat template.txt | for param in ${scriptParams} ; do i=$((++i)) ; echo $i - $param; done

1 - test1,test2,test3

Oops..

scriptParams="test1 test2 test3"

cat template.txt | for param in ${scriptParams} ; do i=$((++i)) ; echo $i - $param; done

1 - test1
2 - test2
3 - test3

Ok, looks better...

cat template.txt | for param in ${scriptParams} ; do i=$((++i)) ; sed -e "s/\${$i}/$param/" ; done
param1=test1
param2=${2}
param3=${3}

Ooops... so what's the problem? Well, the first sed command "eats" all the input. You haven't built a pipeline, where one sed command feeding the next... You have three seds trying to read the same input. Obviously the first one processed the whole input.

Ok, let's take a different approach, let's create the arguments for a single sed command (note: the "" is there to force echo not to interpret -e as an command line switch).

sedargs=$(for param in ${scriptParams} ; do i=$((++i)); echo "" -e "s/\${$i}/$param/"; done)
cat template.txt | sed $sedargs

param1=test1
param2=test2
param3=test3

That's it. Note that this isn't perfect, you can have all sort of problems if the replace texts are complex (e.g.: contain space).

Let me think how to do this in a better way... (well, the obvious solution which comes to mind is not to use a shell script for this task...)

Update: If you want to build a proper pipeline, here are some solutions: How to make a pipe loop in bash

Community
  • 1
  • 1
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • Your code gave error --> sed: -e expression #1, char 2: unknown command: `-' – M.FevziKorkutata Sep 06 '13 at 18:32
  • works here, no idea what you're doing. do you have a different template file or `scriptParams`?? – Karoly Horvath Sep 06 '13 at 18:36
  • You did it with two line. When I worked your script as below, could not get the expected result. **Your script:** `code`scriptParams="test1,test2,test3" sedargs=$(for param in ${scriptParams} ; do i=$((++i)); echo "" -e "s/\${$i}/$param/"; done) cat template.txt | sed $sedargs `code` **RESULT:** param1=test1,test2,test3 param2=${2} param3=${3} – M.FevziKorkutata Sep 06 '13 at 18:44
  • no, my script: `scriptParams="test1 test2 test3"`. you can replace `,` with `sed` – Karoly Horvath Sep 06 '13 at 20:35
1

You can do that with just bash alone:

#!/bin/bash
scriptParams=("test1" "test2" "test3")  ## Better store it as arrays.
while read -r line; do
    for i in in "${!scriptParams[@]}"; do  ## Indices of array scriptParams would be populated to i starting at 0.
        line=${line/"\${$((i + 1))}"/"${scriptParams[i]}"}  ## ${var/p/r} replaces patterns (p) with r in the contents of var. Here we also add 1 to the index to fit with the targets.
    done
    echo "<br>$line</br>"
done < template.txt

Save it in a script and run bash script.sh to get an output like this:

<br>param1=test1</br>
<br>param2=test2</br>
<br>param3=test3</br>
konsolebox
  • 72,135
  • 12
  • 99
  • 105
1

If you intend to use an array, use a real array. sed is not needed either:

$ cat template
param1=${1}
param2=${2}
param3=${3}

$ scriptParams=("test one" "test two" "test three")
$ while read -r l; do for((i=1;i<=${#scriptParams[@]};i++)); do l=${l//\$\{$i\}/${scriptParams[i-1]}}; done; echo "$l"; done < template
param1=test one
param2=test two
param3=test three
Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71