如何远程运行 perl regex 命令

如何远程运行 perl regex 命令

我得到了这个在远程服务器上完美运行的命令

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

但当我尝试通过将其保存为shell 函数像这样:

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
}

$1远程服务器的 IP 在哪里

它返回此错误:

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.

我该怎么做呢?

答案1

您使用的反引号告诉 Perl 将其内部的所有内容作为命令传递到底层 shell - 就像 exec 或 system() 所做的那样。 这里'讨论 Perl 中的反引号的链接。

您确实需要引用远程服务器的整个 perl 命令,但您必须使用双引号。然后您必须转义内部双引号和否则会扩展的变量。

尝试一下:

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

我还转义了 glob 后的左括号,因为 perl 对此有抱怨。

另外,我认为您不需要在连接上强制使用伪 tty,因此您可能可以删除-t。如果这给您带来麻烦,那么我会-T首先尝试禁用伪 TTY 创建。

答案2

以下是 Guy 答案的几个替代方案。

我缩短了你的原始命令以使其(稍微)更易读:

perl -ne 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' /var/log/syslog

现在有了ssh,如果你将 perl 代码放在双引号中,你可以使用qq{}inside,而不是转义双引号。但是,你仍然需要转义变量$

ssh -i $id $user@$host 'perl -ne "print qq{\$1,\$2,\$3\n} if /^([^\[]*)(?:.*(?!SmsJob).)*/" /var/log/syslog'

更具可读性的替代方法是使用@choroba 评论中的建议:关闭并重新打开引号:

ssh -i $id $user@$host 'perl -ne ' "'" 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' "'" /var/log/syslog

或者稍微缩短一点,将第一部分放在双引号中:

ssh -i $id $user@$host "perl -ne '" 'print "$1,$2,$3\n" if /^([^\[]*)(?:.*(?!SmsJob).)*/' "'" /var/log/syslog

(使用本地 Ubuntu 16.04 和远程 Debian 9 进行测试)

相关内容