使用sed的多行bash删除前导空格:在命令参数中错误地保留了引号 [英] Multiline bash using sed to remove leading whitespace: quotes erroneously preserved in command argument
问题描述
我正在运行这段代码:
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屋!