I got this command that works perfectly on the remote server

perl -ne 'print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/' /path/to/file.log

but then when I try to run it locally by saving it as a shell function like so:

function getRemoteLogs()
    ssh -i $ssh_key_file ubuntu@$1 -t 'perl -ne `print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/` /path/to/file.log' > local.txt

where $1 is the ip of the remote server

it returns this error:

bash: command substitution: line 0: syntax error near unexpected token `('
bash: command substitution: line 0: `print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/'
Unknown regexp modifier "/w" at -e line 1, at end of line
Unknown regexp modifier "/w" at -e line 1, at end of line
Unknown regexp modifier "/w" at -e line 1, at end of line
syntax error at -e line 1, near "18.log
Execution of -e aborted due to compilation errors.

how do I do this?

  • 1
    ` has a totally different meaning to '. – choroba Mar 15 at 13:46
  • great! and so now do I use ' properly instead of `? – abbood Mar 15 at 13:52
  • this isn't working ssh -i $ssh_key_file ubuntu@$1 -t 'perl -ne \'print "$1,$2,$3\n" if /^[^\[]*\[\K([^]]+)[^{]*{[^[]*\["\K([^"]+)(?:(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/\' /var/www/toters/storage/logs/info-2019-02-18.log' > local.txt – abbood Mar 15 at 13:55
  • 1
    You can't escape ' inside a '. You need to end the outer quotes, escape the quote, and start the quotes again. – choroba Mar 15 at 13:56

The backticks you are using tell Perl to pass everything inside them to the underlying shell as a command - like exec or system() would do. Here's a link that discusses backticks in Perl.

You do need to quote the whole perl command for the remote server, but you will have to use double quotes. Then you must escape the inner double quotes and the variables that would otherwise expand.

Try this out:

ssh -i $ssh_key_file ubuntu@<remote ip> "perl -ne 'print \"\$1,\$2,\$3\n\" if /^[^\[]*\[\K([^]]+)[^{]*\{[^[]*\[\"\K([^\"]+)(?!SmsJob).)*SmsJob:\K([0-9a-f]+)/' /path/to/file.log" > local.txt

I also escaped the left brace after the glob, because perl complained about it.

Also, I don't think you need to force a pseudo tty on the connection, so you can probably drop -t. If that gives you trouble then I would try it with -T first to disable pseudo TTY creation.

  • 1
    You do need to quote the whole command, as SSH does not preserve individual arguments – it just concatenates them and the result is used as a single argument for /bin/sh -c "..." (similarly to how 'eval' works). The remote side wouldn't know that the part after -ne had been single-quoted locally. – grawity Mar 15 at 14:19
  • Okay, thank you for that correction. But he could use double quotes, right? That way he could have the single quotes preserved in the command. I am finally at a computer now, so I will do some testing on this. – Guy Gastineau Mar 15 at 14:24
  • 1
    Yes, but the inner double quotes and the Perl $variables would need to be backslash-escaped in addition to that. – grawity Mar 15 at 14:26
  • Sure, that is what I was about to check. After I do this actual testing I'll edit my answer above. Thanks for the help ;) – Guy Gastineau Mar 15 at 14:27
  • 1
    Trick for bash 5.0 and later: cmd=(perl -ne 'print "$1,$2,$3\n" if /someregex/' /path/to/file.log); ssh $host "${cmd[*]@Q}" – grawity Mar 15 at 14:39

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.