ran1n
ran1n

Reputation: 157

how to escape the < <() idiom in perl

I have a system command which i am trying to execute, but it gives me error "Syntax error: redirection unexpected"

Trying command:

datamash -ft, -g 1 mean 3 mean 4 < <(tail -n +2 yourfile | sort -t, -k1,2) | cut -d, -f1,2,5,6 

I tried readpipe and also escaped the < < with \< \<, but doesn't work.

below command doesn't work ==>

`datamash -ft, -g 1 mean 3 mean 4 \< \<(tail -n +2 yourfile | sort -t, -k1,2) | cut -d, -f1,2,5,6`

Upvotes: 2

Views: 80

Answers (2)

ikegami
ikegami

Reputation: 385655

Backticks aka readpipe expect a command passed to sh (or cmd in Windows). You appear to have a bash command rather than a sh command. Fixed:

`bash -c 'datamash -ft, -g 1 mean 3 mean 4 < <(tail -n +2 yourfile | sort -t, -k1,2) | cut -d, -f1,2,5,6'`

If you had vars to interpolate, it would look like

use String::ShellQuote ( shell_quote );

my $qfn = '...';
my $tail_cmd = shell_quote('tail', '-n', '+2', $qfn);
my $bash_cmd = "datamash -ft, -g 1 mean 3 mean 4 < <( $tail_cmd | sort -t, -k1,2 ) | cut -d, -f1,2,5,6";
my $sh_cmd = shell_quote('bash', '-c', $bash_cmd);
`$sh_cmd`

As @chepner noticed, the bash command can be converted into a simpler command that's compatible with sh. This reduces the first snippet to the following:

`tail -n +2 yourfile | sort -t, -k1,2 | datamash -ft, -g 1 mean 3 mean 4 | cut -d, -f1,2,5,6'`

This doesn't help us get away from using shell_quote in the second snippet, but it does reduce it it the following:

use String::ShellQuote ( shell_quote );

my $qfn = '...';
my $tail_cmd = shell_quote('tail', '-n', '+2', $qfn);
my $sh_cmd = "$tail_cmd | sort -t, -k1,2 | datamash -ft, -g 1 mean 3 mean 4 | cut -d, -f1,2,5,6";
`$sh_cmd`

Upvotes: 2

chepner
chepner

Reputation: 531055

I wouldn't even bother using process substitution here. Just use an ordinary pipeline:

`tail -n +2 yourfile | sort -t, -k1,2 | datamash -ft, -g 1 mean 3 mean | cut -d, -f1,2,5,6`

Process substitution is most useful when a command (like datamash) needs to run in the current shell, or when you want to feed the output of one command to another command that only reads from a named file, not its standard input. Neither case applies here.

Upvotes: 3

Related Questions