0

为了切入正题,以下内容(源自Charles Duffy对相关问题的回复 - 请参阅他的回答)将是我要求的可接受格式:

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
)"

请注意,每当我试图拆分为多行的命令需要它时,都会有一个尾随空格:

sshfs 
foo_user@fooserver.com:/sftp_folder 
  /var/sshfs.sandbox/server.com 
  -o 

并且对于必须在没有中间空格的情况下连接的选项没有尾随空格:

user=foo_user
,reconnect
,ServerAliveInterval=15
,ServerAliveCountMax=3

连接后,命令变为:

sshfs foo_user@fooserver.com:/sftp_folder /var/sshfs.sandbox/server.com -o user=foo_user,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3

但是,有人告诉我尾随空格是个坏主意(再次,请参阅Charles Duffy回复以了解动机)

因此我想知道。有没有办法实现这三个:

  1. 将声明全部“放在一起”。
  2. 没有尾随空格。
  3. 使“页眉”和“页脚”固定并在其他脚本中复制粘贴而无需修改。

我正在考虑使用尾部反斜杠并修改解析表达式:

{ sed -E -e 's/^[ ]+//;' -e ':a;N;$!ba;s/\n//g' | tr -d '\n'; }

这样我就可以实现上述所有三个。

4

2 回答 2

0

希望这会做你想做的事。

首先,定义一个函数,用于解析在标准输入上接收到的命令。

#!/bin/bash

execute_command()
{
  local -a command=()
  local arg=
  while IFS= read -r line
  do
    [[ $line =~ [[:blank:]]*(.*[^[:blank:]\\])(\\?)[[:blank:]]*$ ]]
    if
      [[ ${BASH_REMATCH[2]} ]]
    then
      arg+=${BASH_REMATCH[1]}
    else
      command+=("$arg${BASH_REMATCH[1]}")
      arg=
    fi
  done
  "${command[@]}"
}

然后,通过在每行末尾留下一个斜杠来调用此函数,您希望下一行被视为同一参数的一部分。上面的代码不会执行任何解析,因此您不能将两个参数放在同一行(在您的示例中,您没有这样做,因此我认为这是您可以接受的限制)。

execute_command <<'____COMMAND'
sshfs
foo_user@fooserver.com:/sftp_folder
  /var/sshfs.sandbox/server.com
  -o
    user=foo_user\
    ,reconnect\
    ,ServerAliveInterval=15\
    ,ServerAliveCountMax=3
____COMMAND

这为您提供了一个非常简单、可重用的“标题”,不需要(但允许)尾随空格并允许在所有行上使用前导空格,同时尽可能少地引入繁重/怪异的语法。

于 2017-04-23T10:34:00.253 回答
0

您是否考虑过使用带反斜杠的多行命令?这使得尾随空间清晰可见。

来自 Bash 手册:

3.1.2.1 转义字符

不带引号的反斜杠 '\' 是 Bash 转义字符。它保留后面的下一个字符的文字值,但换行符除外。如果出现 \newline 对,并且反斜杠本身没有被引用,则 \newline 被视为行继续(即,它从输入流中删除并被有效忽略)。

sshfs \
foo_user@fooserver.com:/sftp_folder \
/var/sshfs.sandbox/server.com \
-o \
user=foo_user\
,reconnect\
,ServerAliveInterval=15\
,ServerAliveCountMax=3,\

反斜杠/换行技巧是命令正常解析的一部分,除了忽略换行之外没有其他效果,因此您可以按照通常的方式使用引号。

就表达命令本身而言,可能有点不干净,但不需要此处文档或额外调用sed.

话虽如此,CharlesDuffy 在回答您的原始问题时推荐了基于数组的解决方案,并且根据我的经验,将命令和参数放入数组中是解决许多问题的简单有效的解决方案。您是否有不想使用此方法的原因?

于 2017-04-21T08:17:14.210 回答