1

In my bash script, I'm going to have two variables called "args1" and "args2". Each one of them is going to have content like this:

Matching cluster names:
[a-z]+
[a-z]+
...

So "args1" could be:

Matching cluster names:
dev1ff
dev2ff

and "args2" could be:

Matching cluster names:
dev2ff
dev3ff

I need to combine these to produce:

Matching cluster names:
dev1ff
dev2ff
dev3ff

I can get close to this with this line:

echo "$(echo "$args1" | grep -v "^Matching") $(echo "$args2" | grep -v "^Matching")" | sort -u

This produces something roughly like this:

Matching clusters:
dev1ff
dev2ff dev3ff

The actual names are immaterial, but the issue is that I'm unable to jam a newline between the first and second block. I tried several variations of things in that space between the two "$(...)" blocks, but nothing worked.

  • what about adding the newline character in the echo list, i.e. echo -e "$(echo "$args1" | grep -v "^Matching") \n $(echo "$args2" | grep -v "^Matching")" | sort -u. Notice the -e in the main echo – Brahim Gaabab May 18 '22 at 21:03
  • @BrahimGaabab, that would do it, but note that you also added spaces there, on both sides of the newline. That'll make the last and first items in the lists different. But there's seldom need for echo "$(...)". – ilkkachu May 18 '22 at 21:12
  • Taking both comments, I have my answer. :) thanks. That works. – David M. Karr May 18 '22 at 21:19

1 Answers1

1

Since the command substitution removes any trailing newlines, you get the space you had there between the two command substitutions as the only thing separating them. Hence the result.

With any echo that supports -e, you could use

echo -e "$(...)\n$(...)" | sort -u

to put a newline in the between instead. Though if your data has backslashes, that would have echo convert them, too. To avoid that, you could use printf like so:

printf "%s\n" "$(...)" "$(...)" | sort -u

(The format string is repeated as many times as needed, so with two arguments, "%s\n" works the same as %s\n%s\n. Also you might want to use printf instead of echo anyway, see Why is printf better than echo?)


But you don't really need the command substitutions; echo "$(something)" is close to just running something directly. You can group the two commands you want to direct to sort -u with curly braces:

{ echo "$args1" | grep -v "^Matching"; echo "$args2" | grep -v "^Matching"; } | sort -u

or, noting that the two greps both do the same thing, move the grep outside the braces:

{ echo "$args1"; echo "$args2"; } | grep -v "^Matching" | sort -u

In the above two, you could replace the echos with some other command that produces that output, without needing to go through a shell variable.

But if you do have the lists in shell variables, you could also use printf to print both at the same time without needing to group multiple commands:

printf "%s\n" "$args1" "$args2" | grep -v "^Matching" | sort -u
ilkkachu
  • 138,973
  • printf is better than echo -e as it's more portable - it's going to work and echo options are not equally respected. – tansy May 19 '22 at 00:15