Perl系统中的awk命令不起作用

nx7onnlm  于 2022-11-15  发布在  Perl
关注(0)|答案(2)|浏览(209)

我正在编写一个执行Awk命令的小Perl脚本:
我试着交换一个文件中的两列,这个文件是这样的:

domain1,ip1
domain2,ip2
domain3,ip3

结果应该是

ip1,domain1
ip2,domain2
ip3,domain3

调用awk的Perl命令如下所示:

system("ssh -p 22 root\@$mainip 'awk -F, '{print $2,$1}' OFS=, /root/archive/ipdomain.txt > /root/ipdom.txt'");

这是我得到的错误:

awk: cmd. line:1: {print
awk: cmd. line:1:       ^ unexpected newline or end of string

有什么建议吗?

mzillmmw

mzillmmw1#

有了分层的命令和所有需要正确处理的多级引用和转义,[2]难怪它会失败。像这样的复杂命令总是很棘手,但库帮助很大。
在shell中运行的带引号的字符串可以用String::ShellQuote ‡构成

use warnings;
use strict;
use feature 'say';

use String::ShellQuote qw(shell_quote);

die "Usage: $0 file outfile\n" if @ARGV != 2;

my ($file, $out) = @ARGV;

my @cmd_words = 
    ( 'ssh', 'hostname', 'awk', q('{print $2 $1}'), $file, '>', $out );

my $cmd = shell_quote @cmd_words;

system($cmd);

请注意,单引号中的q()操作符如何使我们能够很好地传递单引号。
这将交换文件每一行的前两个字,并使用awk将它们打印出来,然后将输出重定向到远程主机上的一个文件。在我的测试中,它的工作与预期的一样(使用真实的的主机名)。请根据需要进行调整。
另一个可能的改进是使用ssh的库,如Net::OpenSSH
要在上述程序中使用的完整命令(如问题中的命令)

my @cmd_words = (
    'ssh', '-p', '22', "root\@$mainip", 
    'awk', '-F,', q('{print $2,$1}'), 'OFS=,', $file, '>', $out );

用问题中的文件进行测试。
makeVoiceBot answer是信息丰富,它得到了一半的方式,但我发现需要

system("ssh hostname \"awk '{print \\\$2 \\\$1}' $path\"");

这在我的测试中有效(在系统I ssh to上)。我尽量避免需要处理这样的引用和转义。
†这是一个运行ssh的shell命令,然后在远程系统上执行一个同样运行shell的命令,以便运行awk并将其输出重定向到一个文件。
比标题中所说的“*awk命令 *”多一点。
‡这个库可以为bash准备一个命令(截至本文撰写之时),但至少可以查看它的源代码,并根据自己的shell对其进行调整。

ovfsdjhp

ovfsdjhp2#

我在这里使用的是一个简短的示例

system("ssh localhost 'awk '{print $2,$1}' file.txt'")

system() sees:
    ssh localhost 'awk '{print $2,$1}' file.txt'
local shell expands:
    ssh
    localhost
    awk 
    {print
    $2,$1}
     file.txt
local shell replaces $1 and $2 (positional args) with empty strings:
    ssh
    localhost
    awk 
    {print
    ,}
     file.txt
ssh executes:
    ssh localhost awk {print ,} file.txt
remote shell gets:
    awk
    {print
    ,}
    file.txt

因此,远程shell运行awk时将{print作为其程序参数,从而导致所描述的错误。

system("ssh localhost \"awk '{print \$2,\$1}' file.txt\"")

system() sees:
    ssh localhost "awk '{print \$2,\$1}' file.txt"
local shell expands:
    ssh
    localhost
    awk '{print \$2,\$1}' file.txt
ssh executes
    ssh localhost awk '{print \$2,\$1}' file.txt
remote shell gets
    awk
    {print \$2,\$1}
    file.txt
remote shell expands \ escapes
    awk
    {print $2,$1}
    file.txt

远程awk现在获取{print $2,$1}作为其程序参数,并成功执行。

相关问题