经过一些实验,这似乎是您所需要的:
snprintf(command, sizeof(command), "ssh %s@%s grep -c \\\"%s\\\" %s%s",
username, hostname, search_string, directory, file);
您需要多个反斜杠,因为涉及多个反斜杠解释器。
- C 编译器:它将每个三个反斜杠序列中的前两个反斜杠视为一个反斜杠。第三个反斜杠转义双引号,在
command
字符串中嵌入双引号。然后命令字符串包含\"
两次。
- 还有另一个处理反斜杠的过程,决定它在哪里有点棘手,但需要它们才能获得正确的结果,如实验所示。
工作代码——远程执行,正确的结果
这是一些演示代码工作。本地程序被调用pop
。里面的所有东西都是硬连线的,因为我很懒(但我把远程主机名与我实际测试过的主机名相比)。该程序/u/jleffler/linux/x86_64/bin/al
列出其收到的参数,每行一个。对于这种情况,我发现它是一个非常有用的工具。请注意,参数al
是用双空格精心制作的,以显示参数何时被视为一对多。
$ ./pop
Command: <<ssh jleffler@remote.example.com /u/jleffler/linux/x86_64/bin/al \"x y z\" \"pp qq rr\">>
jleffler@remote.example.com's password:
Response: <<x y z>>
Response: <<pp qq rr>>
$
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char command[512];
char const *arg1 = "x y z";
char const *arg2 = "pp qq rr";
char const *cmd = "/u/jleffler/linux/x86_64/bin/al";
char const *hostname = "remote.example.com";
char const *username = "jleffler";
snprintf(command, sizeof(command), "ssh %s@%s %s \\\"%s\\\" \\\"%s\\\"",
username, hostname, cmd, arg1, arg2);
printf("Command: <<%s>>\n", command);
FILE *fp = popen(command, "r");
char line[512];
while (fgets(line, sizeof(line), fp) != 0)
{
line[strlen(line)-1] = '\0';
printf("Response: <<%s>>\n", line);
}
pclose(fp);
return(0);
}
变体 1——远程执行,错误的结果
$ ./pop1
Command: <<ssh jleffler@remote.example.com /u/jleffler/linux/x86_64/bin/al "x y z" "pp qq rr">>
jleffler@remote.example.com's password:
Response: <<x>>
Response: <<y>>
Response: <<z>>
Response: <<pp>>
Response: <<qq>>
Response: <<rr>>
$
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char command[512];
char const *arg1 = "x y z";
char const *arg2 = "pp qq rr";
char const *cmd = "/u/jleffler/linux/x86_64/bin/al";
char const *hostname = "remote.example.com";
char const *username = "jleffler";
snprintf(command, sizeof(command), "ssh %s@%s %s \"%s\" \"%s\"",
username, hostname, cmd, arg1, arg2);
printf("Command: <<%s>>\n", command);
FILE *fp = popen(command, "r");
char line[512];
while (fgets(line, sizeof(line), fp) != 0)
{
line[strlen(line)-1] = '\0';
printf("Response: <<%s>>\n", line);
}
pclose(fp);
return(0);
}
变体 2 — 本地执行,(不同)错误结果
$ ./pop2
Command: <<al jleffler@remote.example.com /u/jleffler/linux/x86_64/bin/al \"x y z\" \"pp qq rr\">>
Response: <<jleffler@remote.example.com>>
Response: <</u/jleffler/linux/x86_64/bin/al>>
Response: <<"x>>
Response: <<y>>
Response: <<z">>
Response: <<"pp>>
Response: <<qq>>
Response: <<rr">>
$
本地 shell 在双引号之前不需要反斜杠;事实上,添加它会出错。
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char command[512];
char const *arg1 = "x y z";
char const *arg2 = "pp qq rr";
char const *cmd = "/u/jleffler/linux/x86_64/bin/al";
char const *hostname = "remote.example.com";
char const *username = "jleffler";
snprintf(command, sizeof(command), "al %s@%s %s \\\"%s\\\" \\\"%s\\\"",
username, hostname, cmd, arg1, arg2);
printf("Command: <<%s>>\n", command);
FILE *fp = popen(command, "r");
char line[512];
while (fgets(line, sizeof(line), fp) != 0)
{
line[strlen(line)-1] = '\0';
printf("Response: <<%s>>\n", line);
}
pclose(fp);
return(0);
}
变体 3 — 本地执行,正确的结果
$ ./pop3
Command: <<al jleffler@remote.example.com /u/jleffler/linux/x86_64/bin/al "x y z" "pp qq rr">>
Response: <<jleffler@remote.example.com>>
Response: <</u/jleffler/linux/x86_64/bin/al>>
Response: <<x y z>>
Response: <<pp qq rr>>
$
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char command[512];
char const *arg1 = "x y z";
char const *arg2 = "pp qq rr";
char const *cmd = "/u/jleffler/linux/x86_64/bin/al";
char const *hostname = "remote.example.com";
char const *username = "jleffler";
snprintf(command, sizeof(command), "al %s@%s %s \"%s\" \"%s\"",
username, hostname, cmd, arg1, arg2);
printf("Command: <<%s>>\n", command);
FILE *fp = popen(command, "r");
char line[512];
while (fgets(line, sizeof(line), fp) != 0)
{
line[strlen(line)-1] = '\0';
printf("Response: <<%s>>\n", line);
}
pclose(fp);
return(0);
}