远程服务器上有很多文件,我想将其
fread
放入R中。
如果我在 R 中远程,我可以做
require(data.table)
f <- fread(cmd="awk '{print $0\"\t\"FILENAME}' path/to/myfile*.txt")
我得到了预期的输出,其中文件名作为附加列。
如果我在本地并且需要通过 ssh,我尝试过:
f <- fread(cmd='ssh user@remote awk \\"{print $0 FILENAME}\\" path/to/myfile*.txt')
但我只得到
f
中的文件名,但没有内容。我想我没有让 cmd=
字符串正确通过 ssh,我是否错误地转义了某些内容?我做错了什么?
内容缺失是因为远程服务器中实际执行的命令是
awk "{print sh FILENAME}" path/to/myfile*.txt
,因为在执行$0
之前,"sh"
已被shell(由fread启动)替换为ssh
。这可以通过确认
data.table::fread(cmd='ssh user@remote awk -vsh=123 \\"{print $0 FILENAME}\\" path/to/myfile.txt')
它为您提供了一张
"123path/to/myfile.txt"
表。
要将正确的脚本命令传递给
awk
,你必须做很多转义,几种可能的解决方案是:
data.table::fread(cmd="ssh user@remote awk {print\\\\ \\\\\\$0\\\\,FILENAME} path/to/myfile*.txt")
# that's a lot of "\"'s
data.table::fread(cmd="ssh user@remote awk '{print\\ \\$0\\,FILENAME} path/to/myfile*.txt")
# A lot of characters still requires escaping, including ` `, `,`, `$` and `"`
data.table::fread(cmd="ssh user@remote awk \\''{print $0,FILENAME}'\\' path/to/myfile*.txt")
# now you can write awk scripts almost natively, only `\` and `"` require escaping.
要进行此类转义,首先,您需要在远程服务器中执行命令,例如,
awk '{print $0"\t"FILENAME}' path/to/myfile*.txt
# or without `'`
awk {print\ \$0\"\\t\"FILENAME} path/to/myfile*.txt
# if you use `,` in the script, either `{`, `}` or `,` should be escaped
awk \{print\ \$0,FILENAME} path/to/myfile*.txt
awk
将脚本参数作为一个参数,因此如果不加引号,
应该被转义。$0
将被替换,除非它被 '
引用,或其 $
被转义。\
将“按原样”保留其后面的字符,除非它被 '
引用。{A,B}
将展开(大括号展开),除非 {
、,
或 }
中的任何一个被转义。那么你应该在本地 shell 中转义该命令:
# keep the statement using `''` quotation
ssh user@remote awk \''{print $0"\t"FILENAME}'\' path/to/myfile*.txt # the `'` can be escape using `\`
ssh user@remote awk '{print\ \$0\"\\t\"FILENAME}' path/to/myfile*.txt
ssh user@remote awk '\{print\ \$0,FILENAME}' path/to/myfile*.txt
# otherwise, escape anything that can break an argument or be substituted by the local shell
ssh user@remote awk \'{print\ \$0\"\\t\"FILENAME}\' path/to/myfile*.txt
ssh user@remote awk {print\\ \\\$0\\\"\\\\t\\\"FILENAME} path/to/myfile*.txt
ssh user@remote awk \\\{print\\\ \\\$0,FILENAME} path/to/myfile*.txt
最后你转义了 R 字符串中的所有
\
和引号:
cmd="ssh user@remote awk \\''{print $0\"\\t\"FILENAME}'\\' path/to/myfile*.txt"
# really A LOT of `\`'s
cmd='ssh user@remote awk {print\\\\ \\\\\\$0\\\\\\"\\\\\\\\t\\\\\\"FILENAME} path/to/myfile*.txt'
现在您可以享受从远程服务器读取文件的乐趣,而无需创建任何中间文件!