Your code "works" as it stands. You should always say what you mean by "not working".
What I think is the problem is that your code is working exactly as you describe. It finds "those elements from @txd which contains any of the elements of @uarts" whereas I think you need those elements that end with any of the strings in @uarts.
As it stands your program outputs
PIO_uart_1 PIO_2_uart_1 PIO_uart_10
PIO_uart_10
PIO_uart_3
PIO_uart_9
so when checking for uart_1 it is finding PIO_uart_10 because the former is a substring of the latter. To look for elements that end with a given uart string you just need to add an end-of-line anchor to the regex so that it becomes
@array = grep { $_ =~ /$uarts[$i]$/ } (@txd)
That changes the output to
PIO_uart_1 PIO_2_uart_1
PIO_uart_10
PIO_uart_3
PIO_uart_9
which I hope is what you want?
But it could be written a little better. It is best to loop over the contents of an array unless you specifically need the index, and there is no need for @array to be a global variable (and it could be anmed a lot better) so this will work for you
use strict;
use warnings;
my @uarts = qw(uart_1 uart_10 uart_3 uart_9 );
my @txd = qw(PIO_uart_1 PIO_2_uart_1 PIO_uart_3 PIO_uart_10 PIO_uart_5 PIO_uart_9 PIO_uart_7);
for my $uart ( @uarts ) {
my @matches = grep /$uart\z/, @txd;
print "@matches\n";
}
output
PIO_uart_1 PIO_2_uart_1
PIO_uart_10
PIO_uart_3
PIO_uart_9
forto distinguish it from a function call. Take a look at perldoc perlstyle for the most common standards