sja
sja

Reputation: 2392

Shell: Filter list by array of sed expressions

I have a list like this:

> echo $candidates
ENV-NONPROD-SANDBOX
ENV-NONPROD-SANDBOX-SECRETS
ENV-NONPROD-DEMO
ENV-NONPROD-DEMO-SECRETS
ENV-PROD-EU
ENV-PROD-EU-SECRETS
ENV-PROD-US
ENV-PROD-US-SECRETS

I also have a dynamically created list of expressions which I want to apply as filters (AND) to narrow that list to possible candidates:

$ filters=('/-SECRETS/!d' '/-NONPROD/!d') # static exanmple

Then I concatenate this and try to apply, but that does not work:

$ filterParam=$(printf "-e '%s' " "${filters[@]}")
$ echo $filterParam
-e "/-SECRETS/!d" -e "/-NONPROD/!d"

$ echo "$candidates" | sed $filterParam
sed: 1: " '/-SECRETS/\!d'  ...": invalid command code '

The strange thing: If I execute it manually, it works!

> echo "$candidates" | sed -e "/-SECRETS/!d" -e "/-NONPROD/!d"
ENV-NONPROD-SANDBOX-SECRETS
ENV-NONPROD-DEMO-SECRETS

I execute this on macOS and zsh 5.8.1 (x86_64-apple-darwin21.0)

Upvotes: 1

Views: 289

Answers (2)

user1934428
user1934428

Reputation: 22227

When you do a

sed $filterParam

in zsh, sed is invoked with one single argument, which is the content of the variable filterParam. sed does not know how to handle this.

If you would type the parameters explicitly, i.e.

sed -e "/-SECRETS/!d" -e "/-NONPROD/!d"

sed is invoked with four arguments, and this is what sed understands.

In bash, in the command

sed $filterParam

the value of filterParam would be split at the spaces and each "word" would be passed as a separate argument. In your concrete setting, this would make have sed receive 4 arguments.

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 141145

filterParam=$(printf "-e '%s' "

No, you can't store command line arguments in variables. Read https://mywiki.wooledge.org/BashFAQ/050 .

You can use bash arrays, which you already use to store filters, so just use them:

sedargs=()
for i in "${filters[@]}"; do
   sedargs+=(-e "$i")
done
sed "${sedargs[@]}"

But sed is sed, just join array elements with a newline or a semicolon, which delimits sed expressions:

sed "$(printf "%s\n" "${filters[@]}")"

Upvotes: 1

Related Questions