いくつかの実験の後、これはあなたが必要とするものである可能性が高いようです:
snprintf(command, sizeof(command), "ssh %s@%s grep -c \\\"%s\\\" %s%s",
username, hostname, search_string, directory, file);
バックスラッシュの複数のインタプリタが関係しているため、複数のバックスラッシュが必要です。
- Cコンパイラ:3つの各シーケンスの最初の2つの円記号を1つの円記号として扱います。3番目の円記号は二重引用符をエスケープし、文字列に二重引用符を埋め込み
command
ます。その場合、コマンド文字列には\"
2回含まれます。
- バックスラッシュを処理する別のプロセスがあり、それがどこにあるかを判断するのは少し難しいですが、実験で示されているように、正しい結果を得るにはバックスラッシュが必要です。
作業コード—リモート実行、正しい結果
これが動作するデモコードです。ローカルプログラムはと呼ばれpop
ます。私は怠惰なので、そこにあるものはすべてハードワイヤードです(ただし、実際にテストしたものと比較して、リモートホスト名を変更しました)。プログラム/u/jleffler/linux/x86_64/bin/al
は、引数を受信したとおりに1行に1つずつリストします。このような状況で非常に便利なツールだと思います。al
の引数は、引数が1対多として扱われる場合を示すために、二重のスペースで慎重に作成されていることに注意してください。
$ ./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">>
$
ローカルシェルは、二重引用符の前に円記号を必要としません。実際、それを追加すると間違ってしまいます。
コード
#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);
}