ari*_*sik 1 linux ssh bash special-characters
我想检查只读文件系统。我写了这个awk命令并且运行良好:
awk '{ if ( $4 ~ /ro,/ && $2 !~ /sys/ ) {print $2} }' /proc/mounts
Run Code Online (Sandbox Code Playgroud)
我想将此命令与ssh. 这不起作用:
$ ssh ip "awk '{ if ( $4 ~ /ro,/ && $2 !~ /sys/ ) {print $2} }' /proc/mounts"
bash: !~: event not found
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?问题是因为波浪号字符吗?
波浪号字符不是罪魁祸首,感叹号才是。
双引号!~会触发本地 shell 中的历史记录替换。请注意,内部单引号在本地并不重要(与此相比,类似的情况;但内部引号在远程 shell 中很重要)。
您需要使!~本地 shell 显示为单引号。问题是您还希望在远程 shell 中使用单引号。因此,您无法轻松嵌套引号。
您可以在本地 shell 中禁用历史记录替换并set +H坚持在本地使用双引号。但请注意,您不希望$4或被$2任何 shell 扩展,包括本地 shell。因此无论如何你都需要在本地使用单引号;$或者用来逃避\,例如\$2。
仅使用未加引号的转义\可以帮助进行不需要的历史替换\!。双引号\!会阻止历史替换,但这\不会消失,它会在以后破坏事情。
可能的方法:
未引用并转义!:
# history substitution may be enabled
ssh ip "awk '{ if ( \$4 ~ /ro,/ && \$2 "\!"~ /sys/ ) {print \$2} }' /proc/mounts"
^^^^-double-quoted locally-^^^^ ^^^^^^^-double-quoted locally-^^^^^^^
unquoted locally ^^
Run Code Online (Sandbox Code Playgroud)禁用历史记录替换:
set +H
ssh ip "awk '{ if ( \$4 ~ /ro,/ && \$2 !~ /sys/ ) {print \$2} }' /proc/mounts"
# re-enable history expansion (invoke `set -H') here if needed
Run Code Online (Sandbox Code Playgroud)对除了内部单引号之外的所有内容进行单引号,这在远程 shell 中至关重要:
# history substitution may be enabled
ssh ip 'awk '"'"'{ if ( $4 ~ /ro,/ && $2 !~ /sys/ ) {print $2} }'"'"' /proc/mounts'
^^^^ ^^^^^^^^^^^^-single-quoted locally-^^^^^^^^^^^^ ^^^^^^^^^^^^^
^ double-quoted locally ^
Run Code Online (Sandbox Code Playgroud)在本地单引号所有内容,在远程 shell 中双引号。这会将您的问题推送到远程 shell,因此您无论如何都需要处理它们:
ssh ip 'awk "{ if ( \$4 ~ /ro,/ && \$2 !~ /sys/ ) {print \$2} }" /proc/mounts'
Run Code Online (Sandbox Code Playgroud)
惊喜!我们逃脱了,$但没有!~;并且没有set +H,但该命令有效。
这是因为在远程端ssh生成一个非交互式shell。非交互式 Bash 启动时默认禁用历史扩展(请注意,远程 shell 最初可能是也可能不是 Bash,它可能支持也可能根本不支持历史记录)。这使得主要问题消失了。如果您ssh以非交互方式运行原始命令,例如在本地脚本中(尽管您仍然需要转义$字符),则相同的机制将对您有所帮助。
| 归档时间: |
|
| 查看次数: |
2446 次 |
| 最近记录: |