I would like to write a function with a loop to construct the command:
cat example.txt | sed ′s/A/1//' | sed ′s/B/2//' | sed ′s/C/3//' | sed ′s/D/4//' …
while taking in a string of A B C D.
example.txt
A
B
C
D
Here is what I have come up with so far but I do not know the syntax to chain piped commands together. I was thinking that I could use echo to construct the string version of the command and then execute it that way but I am wondering if there is a better way to do this.
elements="A B C D"
n=1
for i in $elements ; do
cat example.txt | sed "s/$i/$n/g"
n=$(($n+1))
done
The output makes sense given the commands that I have generated:
cat example.txt | sed "s/A/1/g"
cat example.txt | sed "s/B/2/g"
cat example.txt | sed "s/C/3/g"
cat example.txt | sed "s/D/4/g"
but as stated above I would like to "chain" pipe them together.
>Solution :
Since you tagged this sed, I’m assuming a sed-specific answer is acceptable. This doesn’t require dynamic pipeline elements at all: You can add more operations to a single sed command by adding to its command line argument list.
#!/usr/bin/env bash
# ^^^^- NOT /bin/sh; arrays are a non-POSIX feature
elements=( A B C D ) # use a proper array, not a string
n=1
args=( ) # likewise, using a real array here too
for i in "${elements[@]}"; do # iterate over input array
args+=( -e "s/$i/$n/g" ) # append to operation array
n=$(($n+1))
done
sed "${args[@]}" <example.txt # expand command array onto sed command line
For an approach that doesn’t take advantage of sed behavior and is instead generating a pipeline dynamically (without using eval, which makes it much easier but introduces security problems without used without great care), see the answer to Handling long edit lists in XMLStarlet