用空格向bash函数传递字符串

用空格向bash函数传递字符串,bash,quotes,Bash,Quotes,我有一行是从文件中读到的 line="1 \"Some Text Here\"" 和一个接受两个参数的函数 print() { echo $1 echo $2 } 当我执行 print $line 我得到的输出是 1 "Some 我想要的是 1 Some Text Here 您需要使用变量IFS。在脚本类型中IFS=\”。这应该可以解决您的问题。您需要在脚本类型中IFS=\”使用变量IFS。这应该可以解决您的问题。如果您信任输入,可以使用eval(通常要避免,因为恶意输

我有一行是从文件中读到的

line="1 \"Some Text Here\""
和一个接受两个参数的函数

print() {
    echo $1
    echo $2
}
当我执行

print $line
我得到的输出是

1
"Some
我想要的是

1
Some Text Here

您需要使用变量
IFS
。在脚本类型中
IFS=\”
。这应该可以解决您的问题。

您需要在脚本类型中
IFS=\”
使用变量
IFS
。这应该可以解决您的问题。

如果您信任输入,可以使用
eval
(通常要避免,因为恶意输入字符串可能会做不必要的事情):

但是,即使使用无害的输入字符串,
eval
命令也会在输入字符串包含所谓的shell元字符时中断;()<>

此外,如果字符串碰巧包含类似路径名模式(glob)的标记,例如
*
,它们会在不经意间被扩展;相关的模式字符是:
*?[]

因此,为了使上述内容更加健壮,使用
\
输入字符串中的转义模式字符和元字符如下所示:

eval print "$(sed 's/[][*?&;()<>]/\\&/g' <<<"$line")"
结果:

[1]
[double-quoted string]
[*]
[single-quoted string]
[string-with-;|>-(metachars)]
注意事项和限制

#!/usr/bin/env bash

# Sample function that prints each argument passed to it separately
print() {
    for arg; do
      echo "[$arg]" # enclose value in [] to better see its boundaries
    done
}

# Sample input string with embedded quoted strings, an unqoted
# glob-like string, and an string containing shell metacharacters
line="1 \"double-quoted string\" * 'single-quoted string' string-with-;|>-(metachars)"

# Let `xargs` split the string into lines (-n 1) and read the
# result into a bash array (read -ra).
# This relies on `xargs`' ability to recognize quoted strings embedded
# in a string literal.
IFS=$'\n' read -d '' -ra args <<<"$(xargs -n 1 printf '%s\n' <<<"$line")"

# Now pass the array to the `print` function.
print "${args[@]}"
  • 无引号标记允许使用
    \
    转义嵌入字符,如空格、单引号和双引号

    • 但是,其他字符前面的
      \
      也会被忽略,这可能是不需要的;e、 g.:
      echo'a\b'| xargs#->'ab'
      -使用
      \
      ,或者使用单引号或双引号代替标记
  • 带引号的令牌不需要内部转义,但遗憾的是,不支持嵌入相同类型的引号-转义似乎不起作用

  • 请注意,通常不需要指定
    printf“%s\n”
    作为
    xargs
    执行的命令,因为
    xargs
    默认调用
    echo
    实用程序(而不是shell内置);但是,一些
    echo
    实现识别自己的选项,例如
    -e
    (但不支持
    --
    ),因此第一个输出标记可能会被误认为是选项。
    相比之下,
    printf“%s\n
    在所有情况下都有效

  • 不支持包含嵌入换行符的带引号的字符串。(
    xargs
    在这种情况下报告了一个解析错误)-据推测,这很少会成为问题


如果您信任输入,可以使用
eval
(通常要避免,因为恶意输入字符串可能会做不必要的事情):

但是,即使使用无害的输入字符串,
eval
命令也会在输入字符串包含所谓的shell元字符时中断;()<>

此外,如果字符串碰巧包含类似路径名模式(glob)的标记,例如
*
,它们会在不经意间被扩展;相关的模式字符是:
*?[]

因此,为了使上述内容更加健壮,使用
\
输入字符串中的转义模式字符和元字符如下所示:

eval print "$(sed 's/[][*?&;()<>]/\\&/g' <<<"$line")"
结果:

[1]
[double-quoted string]
[*]
[single-quoted string]
[string-with-;|>-(metachars)]
注意事项和限制

#!/usr/bin/env bash

# Sample function that prints each argument passed to it separately
print() {
    for arg; do
      echo "[$arg]" # enclose value in [] to better see its boundaries
    done
}

# Sample input string with embedded quoted strings, an unqoted
# glob-like string, and an string containing shell metacharacters
line="1 \"double-quoted string\" * 'single-quoted string' string-with-;|>-(metachars)"

# Let `xargs` split the string into lines (-n 1) and read the
# result into a bash array (read -ra).
# This relies on `xargs`' ability to recognize quoted strings embedded
# in a string literal.
IFS=$'\n' read -d '' -ra args <<<"$(xargs -n 1 printf '%s\n' <<<"$line")"

# Now pass the array to the `print` function.
print "${args[@]}"
  • 无引号标记允许使用
    \
    转义嵌入字符,如空格、单引号和双引号

    • 但是,其他字符前面的
      \
      也会被忽略,这可能是不需要的;e、 g.:
      echo'a\b'| xargs#->'ab'
      -使用
      \
      ,或者使用单引号或双引号代替标记
  • 带引号的令牌不需要内部转义,但遗憾的是,不支持嵌入相同类型的引号-转义似乎不起作用

  • 请注意,通常不需要指定
    printf“%s\n”
    作为
    xargs
    执行的命令,因为
    xargs
    默认调用
    echo
    实用程序(而不是shell内置);但是,一些
    echo
    实现识别自己的选项,例如
    -e
    (但不支持
    --
    ),因此第一个输出标记可能会被误认为是选项。
    相比之下,
    printf“%s\n
    在所有情况下都有效

  • 不支持包含嵌入换行符的带引号的字符串。(
    xargs
    在这种情况下报告了一个解析错误)-据推测,这很少会成为问题


根据您的具体情况,使用
shift
可能适合您

例如:

print() {
    echo "$1"
    shift
    echo "$*"
}
这将打印第一个参数,移动参数列表(删除第一个参数),然后打印其余参数

这应该会给你这个结果:

$ text="1 \"Multiple Words Here\""

$ print() {
>     echo "$1"
>     shift
>     echo "$*"
> }


$ print $text
1
"Multiple Words Here"

根据您的具体情况,使用
shift
可能适合您

例如:

print() {
    echo "$1"
    shift
    echo "$*"
}
这将打印第一个参数,移动参数列表(删除第一个参数),然后打印其余参数

这应该会给你这个结果:

$ text="1 \"Multiple Words Here\""

$ print() {
>     echo "$1"
>     shift
>     echo "$*"
> }


$ print $text
1
"Multiple Words Here"

文件格式似乎对引号在
bash
中的工作方式做出了错误的假设。如果可能,将文件更改为使
line
成为一个数组:
line=(1“此处有一些文本”)
。这在从文件读取的行上下文中是否有意义。如果文件中有这样的行格式,会让excel发疯,那么您如何定义
bash
变量
line
?您显示的行不是有效的
bash
赋值语句(不允许等号周围有空格)。我假设这是一个输入错误,而你只是在寻找文件的来源。文件格式似乎对引号在
bash
中的工作方式做出了错误的假设。如果可能,将文件更改为使
line
成为一个数组:
line=(1“此处有一些文本”)
。这在从文件读取的行上下文中是否有意义。宁愿