使用sed的多行bash删除前导空格:在命令参数中错误地保留了引号 [英] Multiline bash using sed to remove leading whitespace: quotes erroneously preserved in command argument

查看:134
本文介绍了使用sed的多行bash删除前导空格:在命令参数中错误地保留了引号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行这段代码:

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中实现多行.请注意,我尝试将其拆分为多行时,命令会在需要时使用尾随空格:

It's my (perhaps clumsy) attempt at having a generic way of achieving multiline in bash. Note that there is a trailing space whenever it is needed by the command I'm trying to split into multple lines:

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

对于没有中间空格的必须串联的选项,没有尾随空格:

And no trailing spaces for options that have to be concatenated without an intervening blank space:

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

如果我在任何地方都没有引号或双引号,那就可以了.如果我运行此命令:

It works ok if I don't have quotes or double quotes anywhere. If I run this:

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的.为什么?

It looks like the quotes are passed to sshfs as part of the "argument". Why?

我现在了解为什么保留引号(ty 查尔斯·达菲-请参见

I understand now why the quotes are preserved (ty Charles Duffy - see his answer below)

我在此答案之后为我的解决方案建模.我需要两次使用sed,一次用于领先空间,另一次用于EOL,这就是为什么我最终使用这些理解的原因. PS:我有前导空格,没有前导制表符,因此用于删除前导制表符的<<-标记没有用

I modelled my solution after this answer. I need to apply sed twice, once for the leading space , and another one for the EOL, and that's why I end up using those comprehensions. PS: I have leading spaces, not leading tabs, hence the <<- marker that removes leading tabs is not useful

我最初的问题是我想要一个可以粘贴在任何脚本中的样板标题/页脚,然后只需键入此标题页脚中包含的命令,就好像我不必担心缩进一样. 我知道我可以通过分配一个变量然后在以后使用结果来解决问题,但是我不想要那样.我希望只能在一个地方输入换行的缩进命令 . 基本上.具有以下特征:

My original problem is that I want a boilerplate header/footer that I can paste in any script, and then just type the command enclosed in this header footer as if I didn't have to worry about indentation. I know I can solve the problem by assigning to a variable and then using the results later on, but I don't want that. I would like to be able to enter the newlined, indented command only in one place. Basically. with these characteristics:

  • 保留实际EOL之前的行尾空格
  • 行尾已删除
  • 删除了新行前导空格

这可能吗?

推荐答案

一种真正有效的方法

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[@]}"


解释为什么另一种方法没有

无引号的扩展通过以下解析步骤,并且仅 经历以下解析步骤:


Explaining why the other approach doesn't

An unquoted expansion goes through the following parsing steps, and only the following parsing steps:

  • 字符串拆分(根据IFS中的字符拆分为多个不同的单词)
  • 全局扩展(替换任何看起来像全局表达式的单词,并带有与该表达式匹配的名称列表).
  • String-splitting (splitting into multiple distinct words based on characters in IFS)
  • Glob expansion (replacement of any word which looks like a glob expression with a list of names matching that expression).

就是这样.没有引号,没有引号删除,没有参数替换等.如果不将引号解析为语法,则变量将导致被解析为单个单词不会;并且在不删除引号的情况下,这些引号在调用的命令中作为文字数据显示.

That's it. No quoting, no quote removal, no parameter substitution, etc. Without quotes being parsed as syntax, variables they would cause to be parsed as a single word aren't parsed in that manner; and without quote removal, those quotes are present as literal data in the commands being invoked.

有关详细讨论,请参见 BashFAQ#50 .

See BashFAQ #50 for a detailed discussion.

这篇关于使用sed的多行bash删除前导空格:在命令参数中错误地保留了引号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆