我正在运行这段代码:
annotate-output $((sed -E 's/^[ ]+//;' <<____COMMAND
sshfs
foo_user@fooserver.com:/sftp_folder
/var/sshfs.sandbox/server.com
-o
user=foo_user
,reconnect
,ServerAliveInterval=15
,ServerAliveCountMax=3
____COMMAND
) | sed -E -e ':a;N;$!ba;s/\n//g')
这是我(也许是笨拙的)尝试在bash中实现多线的通用方法。请注意,只要命令我试图分成多行,就会有一个尾随空格:
sshfs
foo_user@fooserver.com:/sftp_folder
/var/sshfs.sandbox/server.com
-o
并且没有必须连接的选项的尾随空格而没有插入空格:
user=foo_user
,reconnect
,ServerAliveInterval=15
,ServerAliveCountMax=3
如果我在任何地方都没有引号或双引号,它就可以了。如果我运行这个:
annotate-output $((sed -E 's/^[ ]+//;' <<____COMMAND
sshfs
foo_user@fooserver.com:/sftp_folder
"/var/sshfs.sandbox/server.com"
-o
user=foo_user
,reconnect
,ServerAliveInterval=15
,ServerAliveCountMax=3
____COMMAND
) | sed -E -e ':a;N;$!ba;s/\n//g')
我明白了:
fuse: bad mount point `"/var/sshfs.sandbox/server.com"': No such file or directory
看起来引号作为“参数”的一部分传递给sshfs。为什么呢?
我现在明白为什么保留引号(ty Charles Duffy - 请参阅his answer below)
我在this answer之后建模了我的解决方案。我需要两次应用sed,一次用于领先空间,另一次用于EOL,这就是我最终使用这些理解的原因。 PS:我有前导空格,而不是前导标签,因此删除前导标签的&lt;&lt; - 标记无效
我最初的问题是我想要一个可以粘贴在任何脚本中的样板页眉/页脚,然后只需键入此页眉中包含的命令,就像我不必担心缩进一样。 我知道我可以通过分配变量然后稍后使用结果来解决问题,但我不希望这样。我希望能够只在一个地方输入新的,缩进的命令 。 基本上。有这些特点:
这可能吗?
答案 0 :(得分:1)
IFS=, # cause "${array[*]}" to combine all items with commas
options=(
user=foo_user # can put a comment here if you like
reconnect # or here
ServerAliveInterval=15 # or so forth
ServerAliveCountMax=3
)
sshfs_cmd=(
sshfs
foo_user@fooserver.com:/sftp_folder
/var/sshfs.sandbox/server.com
-o "${options[*]}"
)
"${sshfs_cmd[@]}"
不带引号的扩展会经历以下解析步骤,而仅以下解析步骤:
IFS
中的字符分割为多个不同的字)就是这样。没有引用,没有引用删除,没有参数替换等。如果没有引号被解析为语法,它们将导致被解析为单个单词的变量不会以这种方式进行解析;如果没有引用删除,那些引号将作为文本数据出现在被调用的命令中。
有关详细讨论,请参阅BashFAQ #50。
答案 1 :(得分:0)
eval
以下是您想要的 - 删除前导空格而不是尾随空格,并将heredoc内容组合到一个命令中。 (没有必要在命令结尾处保留一个尾随的换行符:eval "true"
即使没有true
以换行符结尾,也能很好地工作。
eval "$(
{ sed -E -e 's/^[ ]+//;' -e ':a;N;$!ba;s/\n//g' | tr -d '\n'; } <<'____COMMAND'
sshfs
foo_user@fooserver.com:/sftp_folder
/var/sshfs.sandbox/server.com
-o
user=foo_user
,reconnect
,ServerAliveInterval=15
,ServerAliveCountMax=3
____COMMAND
)"
需要注意的一些事项:
____COMMAND
)中的印记是引用的。这样可以确保扩展仅在调用eval
之后与之前(当扩展heredoc的内容本身时)之后发生。sed
的调用将多个命令传递给单个-e
调用。为尾随空格赋予语义含义是一种简单的方法来混淆其他读取代码的人。正如标签与空间问题一样,关注使用Makefiles或使用Python的几代开发人员(仅在PEP-8标准化空间之前),使尾随空间与无尾随空间成为语义上有意义的区别将会严重混淆任何阅读您的代码的人,都会导致与自动格式验证冲突(例如当前版本的git
中包含的功能,以便在将来任何行包含尾随空格时发出警告)。